This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Cmd+Shift+Enter.

install.packages('devtools')
trying URL 'https://cran.rstudio.com/bin/macosx/big-sur-arm64/contrib/4.2/devtools_2.4.5.tgz'
Content type 'application/x-gzip' length 421790 bytes (411 KB)
==================================================
downloaded 411 KB

The downloaded binary packages are in
    /var/folders/4q/4mb5qhz51qdgffngk4lqzs540000gn/T//RtmpE16bnd/downloaded_packages
install.packages('Seurat')
trying URL 'https://cran.rstudio.com/bin/macosx/big-sur-arm64/contrib/4.2/Seurat_5.0.1.tgz'
Content type 'application/x-gzip' length 4150196 bytes (4.0 MB)
==================================================
downloaded 4.0 MB

The downloaded binary packages are in
    /var/folders/4q/4mb5qhz51qdgffngk4lqzs540000gn/T//RtmpE16bnd/downloaded_packages
library(Seurat)
Warning: package ‘Seurat’ was built under R version 4.2.3Loading required package: SeuratObject
Warning: package ‘SeuratObject’ was built under R version 4.2.3Loading required package: sp
Warning: package ‘sp’ was built under R version 4.2.3
Attaching package: ‘sp’

The following object is masked from ‘package:IRanges’:

    %over%


Attaching package: ‘SeuratObject’

The following object is masked from ‘package:SummarizedExperiment’:

    Assays

The following object is masked from ‘package:GenomicRanges’:

    intersect

The following object is masked from ‘package:GenomeInfoDb’:

    intersect

The following object is masked from ‘package:IRanges’:

    intersect

The following object is masked from ‘package:S4Vectors’:

    intersect

The following object is masked from ‘package:BiocGenerics’:

    intersect

The following object is masked from ‘package:base’:

    intersect

Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Attaching package: ‘Seurat’

The following object is masked from ‘package:SummarizedExperiment’:

    Assays
library(dplyr)
Warning: package ‘dplyr’ was built under R version 4.2.3
Attaching package: ‘dplyr’

The following object is masked from ‘package:Biobase’:

    combine

The following object is masked from ‘package:matrixStats’:

    count

The following objects are masked from ‘package:GenomicRanges’:

    intersect, setdiff, union

The following object is masked from ‘package:GenomeInfoDb’:

    intersect

The following objects are masked from ‘package:IRanges’:

    collapse, desc, intersect, setdiff, slice, union

The following objects are masked from ‘package:S4Vectors’:

    first, intersect, rename, setdiff, setequal, union

The following objects are masked from ‘package:BiocGenerics’:

    combine, intersect, setdiff, union

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(patchwork)
library(ggplot2)
#Loading matrices from cellranger output
library(Matrix)
Warning: package ‘Matrix’ was built under R version 4.2.3
Attaching package: ‘Matrix’

The following object is masked from ‘package:S4Vectors’:

    expand
matrix_dir = "/Users/pengwu/Documents/Research - Old/scRNAseq/HB1-Jan2019/filtered_feature_bc_matrix/"
barcode.path <- paste0(matrix_dir, "HB1_barcodes.tsv.gz")
features.path <- paste0(matrix_dir, "HB1_features.tsv.gz")
matrix.path <- paste0(matrix_dir, "HB1_matrix.mtx.gz")
mat <- readMM(file = matrix.path)
feature.names = read.delim(features.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
barcode.names = read.delim(barcode.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
colnames(mat) = barcode.names$V1
rownames(mat) = make.unique(feature.names$V2)
# Initialize the Seurat object with the raw (non-normalized data).  Keep all
# genes expressed in >= 3 cells (~0.1% of the data). Keep all cells with at
# least 200 detected genes
HB1 <- CreateSeuratObject(counts = mat, min.cells = 3, min.features = 200, project = "HB1")
Warning: Data is of class dgTMatrix. Coercing to dgCMatrix.
HB1
An object of class Seurat 
18626 features across 4340 samples within 1 assay 
Active assay: RNA (18626 features, 0 variable features)
 1 layer present: counts
#Loading matrices from cellranger output
library(Matrix)
matrix_dir = "/Users/pengwu/Documents/Research - Old/scRNAseq/HB4-Oct2020/outs/filtered_feature_bc_matrix/"
barcode.path <- paste0(matrix_dir, "HB4_barcodes.tsv.gz")
features.path <- paste0(matrix_dir, "HB4_features.tsv.gz")
matrix.path <- paste0(matrix_dir, "HB4_matrix.mtx.gz")
mat <- readMM(file = matrix.path)
feature.names = read.delim(features.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
barcode.names = read.delim(barcode.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
colnames(mat) = barcode.names$V1
rownames(mat) = make.unique(feature.names$V2)
# Initialize the Seurat object with the raw (non-normalized data).  Keep all
# genes expressed in >= 3 cells (~0.1% of the data). Keep all cells with at
# least 200 detected genes
HB4 <- CreateSeuratObject(counts = mat, min.cells = 3, min.features = 200, project = "HB4")
Warning: Data is of class dgTMatrix. Coercing to dgCMatrix.
HB4
An object of class Seurat 
19985 features across 7856 samples within 1 assay 
Active assay: RNA (19985 features, 0 variable features)
 1 layer present: counts
matrix_dir = "/Users/pengwu/Documents/Research - Old/scRNAseq/HB6-Oct2020/outs/filtered_feature_bc_matrix/"
barcode.path <- paste0(matrix_dir, "HB6_barcodes.tsv.gz")
features.path <- paste0(matrix_dir, "HB6_features.tsv.gz")
matrix.path <- paste0(matrix_dir, "HB6_matrix.mtx.gz")
mat <- readMM(file = matrix.path)
feature.names = read.delim(features.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
barcode.names = read.delim(barcode.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
colnames(mat) = barcode.names$V1
rownames(mat) = make.unique(feature.names$V2)
# Initialize the Seurat object with the raw (non-normalized data).  Keep all
# genes expressed in >= 3 cells (~0.1% of the data). Keep all cells with at
# least 200 detected genes
HB6 <- CreateSeuratObject(counts = mat, min.cells = 3, min.features = 200, project = "HB6")
Warning: Data is of class dgTMatrix. Coercing to dgCMatrix.
HB6
An object of class Seurat 
21067 features across 4490 samples within 1 assay 
Active assay: RNA (21067 features, 0 variable features)
 1 layer present: counts
matrix_dir = "/Users/pengwu/Documents/Research - Old/scRNAseq/HB7-Oct2020/outs/filtered_feature_bc_matrix/"
barcode.path <- paste0(matrix_dir, "HB7_barcodes.tsv.gz")
features.path <- paste0(matrix_dir, "HB7_features.tsv.gz")
matrix.path <- paste0(matrix_dir, "HB7_matrix.mtx.gz")
mat <- readMM(file = matrix.path)
feature.names = read.delim(features.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
barcode.names = read.delim(barcode.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
colnames(mat) = barcode.names$V1
rownames(mat) = make.unique(feature.names$V2)
# Initialize the Seurat object with the raw (non-normalized data).  Keep all
# genes expressed in >= 3 cells (~0.1% of the data). Keep all cells with at
# least 200 detected genes
HB7 <- CreateSeuratObject(counts = mat, min.cells = 3, min.features = 200, project = "HB7")
Warning: Data is of class dgTMatrix. Coercing to dgCMatrix.
HB7
An object of class Seurat 
20887 features across 8378 samples within 1 assay 
Active assay: RNA (20887 features, 0 variable features)
 1 layer present: counts
matrix_dir = "/Users/pengwu/Documents/Research - Old/scRNAseq/HB12-Jul2021/outs/"
barcode.path <- paste0(matrix_dir, "HB12_barcodes.tsv.gz")
features.path <- paste0(matrix_dir, "HB12_features.tsv.gz")
matrix.path <- paste0(matrix_dir, "HB12_matrix.mtx.gz")
mat <- readMM(file = matrix.path)
feature.names = read.delim(features.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
barcode.names = read.delim(barcode.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
colnames(mat) = barcode.names$V1
rownames(mat) = make.unique(feature.names$V2)
# Initialize the Seurat object with the raw (non-normalized data).  Keep all
# genes expressed in >= 3 cells (~0.1% of the data). Keep all cells with at
# least 200 detected genes
HB12 <- CreateSeuratObject(counts = mat, min.cells = 3, min.features = 200, project = "HB12")
Warning: Data is of class dgTMatrix. Coercing to dgCMatrix.
HB12
An object of class Seurat 
18040 features across 2318 samples within 1 assay 
Active assay: RNA (18040 features, 0 variable features)
 1 layer present: counts
matrix_dir = "/Users/pengwu/Documents/Research - Old/scRNAseq/HB13-Jul2021/outs/"
barcode.path <- paste0(matrix_dir, "HB13_barcodes.tsv.gz")
features.path <- paste0(matrix_dir, "HB13_features.tsv.gz")
matrix.path <- paste0(matrix_dir, "HB13_matrix.mtx.gz")
mat <- readMM(file = matrix.path)
feature.names = read.delim(features.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
barcode.names = read.delim(barcode.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
colnames(mat) = barcode.names$V1
rownames(mat) = make.unique(feature.names$V2)
# Initialize the Seurat object with the raw (non-normalized data).  Keep all
# genes expressed in >= 3 cells (~0.1% of the data). Keep all cells with at
# least 200 detected genes
HB13 <- CreateSeuratObject(counts = mat, min.cells = 3, min.features = 200, project = "HB13")
Warning: Data is of class dgTMatrix. Coercing to dgCMatrix.
HB13
An object of class Seurat 
18633 features across 3395 samples within 1 assay 
Active assay: RNA (18633 features, 0 variable features)
 1 layer present: counts
matrix_dir = "/Users/pengwu/Documents/Research - Old/scRNAseq/HB14-Apr2022/"
barcode.path <- paste0(matrix_dir, "HB14_barcodes.tsv.gz")
features.path <- paste0(matrix_dir, "HB14_features.tsv.gz")
matrix.path <- paste0(matrix_dir, "HB14_matrix.mtx.gz")
mat <- readMM(file = matrix.path)
feature.names = read.delim(features.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
barcode.names = read.delim(barcode.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
colnames(mat) = barcode.names$V1
rownames(mat) = make.unique(feature.names$V2)
# Initialize the Seurat object with the raw (non-normalized data).  Keep all
# genes expressed in >= 3 cells (~0.1% of the data). Keep all cells with at
# least 200 detected genes
HB14 <- CreateSeuratObject(counts = mat, min.cells = 3, min.features = 200, project = "HB14")
Warning: Data is of class dgTMatrix. Coercing to dgCMatrix.
HB14
An object of class Seurat 
16219 features across 4870 samples within 1 assay 
Active assay: RNA (16219 features, 0 variable features)
 1 layer present: counts
matrix_dir = "/Users/pengwu/Documents/Research - Old/scRNAseq/HB15-2/filtered_feature_bc_matrix/"
barcode.path <- paste0(matrix_dir, "HB15_barcodes.tsv.gz")
features.path <- paste0(matrix_dir, "HB15_features.tsv.gz")
matrix.path <- paste0(matrix_dir, "HB15_matrix.mtx.gz")
mat <- readMM(file = matrix.path)
feature.names = read.delim(features.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
barcode.names = read.delim(barcode.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
colnames(mat) = barcode.names$V1
rownames(mat) = make.unique(feature.names$V2)
# Initialize the Seurat object with the raw (non-normalized data).  Keep all
# genes expressed in >= 3 cells (~0.1% of the data). Keep all cells with at
# least 200 detected genes
HB15 <- CreateSeuratObject(counts = mat, min.cells = 3, min.features = 200, project = "HB15")
Warning: Data is of class dgTMatrix. Coercing to dgCMatrix.
HB15
An object of class Seurat 
18954 features across 2704 samples within 1 assay 
Active assay: RNA (18954 features, 0 variable features)
 1 layer present: counts
matrix_dir = "/Users/pengwu/Documents/Research - Old/scRNAseq/HB16/filtered_feature_bc_matrix/"
barcode.path <- paste0(matrix_dir, "HB16_barcodes.tsv.gz")
features.path <- paste0(matrix_dir, "HB16_features.tsv.gz")
matrix.path <- paste0(matrix_dir, "HB16_matrix.mtx.gz")
mat <- readMM(file = matrix.path)
feature.names = read.delim(features.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
barcode.names = read.delim(barcode.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
colnames(mat) = barcode.names$V1
rownames(mat) = make.unique(feature.names$V2)
# Initialize the Seurat object with the raw (non-normalized data).  Keep all
# genes expressed in >= 3 cells (~0.1% of the data). Keep all cells with at
# least 200 detected genes
HB16 <- CreateSeuratObject(counts = mat, min.cells = 3, min.features = 200, project = "HB16")
Warning: Data is of class dgTMatrix. Coercing to dgCMatrix.
HB16
An object of class Seurat 
18655 features across 2869 samples within 1 assay 
Active assay: RNA (18655 features, 0 variable features)
 1 layer present: counts
matrix_dir = "/Users/pengwu/Documents/Research - Old/scRNAseq/HB17/filtered_feature_bc_matrix/"
barcode.path <- paste0(matrix_dir, "HB17_barcodes.tsv.gz")
features.path <- paste0(matrix_dir, "HB17_features.tsv.gz")
matrix.path <- paste0(matrix_dir, "HB17_matrix.mtx.gz")
mat <- readMM(file = matrix.path)
feature.names = read.delim(features.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
barcode.names = read.delim(barcode.path, 
                           header = FALSE,
                           stringsAsFactors = FALSE)
colnames(mat) = barcode.names$V1
rownames(mat) = make.unique(feature.names$V2)
# Initialize the Seurat object with the raw (non-normalized data).  Keep all
# genes expressed in >= 3 cells (~0.1% of the data). Keep all cells with at
# least 200 detected genes
HB17 <- CreateSeuratObject(counts = mat, min.cells = 3, min.features = 200, project = "HB16")
Warning: Data is of class dgTMatrix. Coercing to dgCMatrix.
HB17
An object of class Seurat 
18919 features across 1420 samples within 1 assay 
Active assay: RNA (18919 features, 0 variable features)
 1 layer present: counts
# The number of genes and UMIs (nGene and nUMI) are automatically calculated
# for every object by Seurat.  For non-UMI data, nUMI represents the sum of
# the non-normalized values within a cell We calculate the percentage of
# mitochondrial genes here and store it in percent.mito using AddMetaData.
# We use object@raw.data since this represents non-transformed and
# non-log-normalized counts The % of UMI mapping to MT-genes is a common
# scRNA-seq QC metric.
mito.features <- grep(pattern = "^MT-", x = rownames(x = HB1), value = TRUE)
percent.mito <- Matrix::colSums(x = GetAssayData(object = HB1, slot = 'counts')[mito.features, ]) / Matrix::colSums(x = GetAssayData(object = HB1, slot = 'counts'))
Warning: The `slot` argument of `GetAssayData()` is deprecated as of SeuratObject 5.0.0.
Please use the `layer` argument instead.
# The [[ operator can add columns to object metadata, and is a great place to stash QC stats
HB1[['percent.mito']] <- percent.mito
rb.genes <- rownames(HB1)[grep("^RP[SL]",rownames(HB1))]
percent.ribo <- Matrix::colSums(x = GetAssayData(object = HB1, slot = 'counts')[rb.genes, ]) / Matrix::colSums(x = GetAssayData(object = HB1, slot = 'counts'))
HB1[['percent.ribo']] <- percent.ribo
VlnPlot(object = HB1, features = c("nFeature_RNA", "nCount_RNA", "percent.mito", "percent.ribo"), ncol = 4)
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.

# The number of genes and UMIs (nGene and nUMI) are automatically calculated
# for every object by Seurat.  For non-UMI data, nUMI represents the sum of
# the non-normalized values within a cell We calculate the percentage of
# mitochondrial genes here and store it in percent.mito using AddMetaData.
# We use object@raw.data since this represents non-transformed and
# non-log-normalized counts The % of UMI mapping to MT-genes is a common
# scRNA-seq QC metric.
mito.features <- grep(pattern = "^MT-", x = rownames(x = HB4), value = TRUE)
percent.mito <- Matrix::colSums(x = GetAssayData(object = HB4, slot = 'counts')[mito.features, ]) / Matrix::colSums(x = GetAssayData(object = HB4, slot = 'counts'))
# The [[ operator can add columns to object metadata, and is a great place to stash QC stats
HB4[['percent.mito']] <- percent.mito
rb.genes <- rownames(HB4)[grep("^RP[SL]",rownames(HB4))]
percent.ribo <- Matrix::colSums(x = GetAssayData(object = HB4, slot = 'counts')[rb.genes, ]) / Matrix::colSums(x = GetAssayData(object = HB4, slot = 'counts'))
HB4[['percent.ribo']] <- percent.ribo
VlnPlot(object = HB4, features = c("nFeature_RNA", "nCount_RNA", "percent.mito", "percent.ribo"), ncol = 4)
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.

# The number of genes and UMIs (nGene and nUMI) are automatically calculated
# for every object by Seurat.  For non-UMI data, nUMI represents the sum of
# the non-normalized values within a cell We calculate the percentage of
# mitochondrial genes here and store it in percent.mito using AddMetaData.
# We use object@raw.data since this represents non-transformed and
# non-log-normalized counts The % of UMI mapping to MT-genes is a common
# scRNA-seq QC metric.
mito.features <- grep(pattern = "^MT-", x = rownames(x = HB6), value = TRUE)
percent.mito <- Matrix::colSums(x = GetAssayData(object = HB6, slot = 'counts')[mito.features, ]) / Matrix::colSums(x = GetAssayData(object = HB6, slot = 'counts'))
# The [[ operator can add columns to object metadata, and is a great place to stash QC stats
HB6[['percent.mito']] <- percent.mito
rb.genes <- rownames(HB6)[grep("^RP[SL]",rownames(HB6))]
percent.ribo <- Matrix::colSums(x = GetAssayData(object = HB6, slot = 'counts')[rb.genes, ]) / Matrix::colSums(x = GetAssayData(object = HB6, slot = 'counts'))
HB6[['percent.ribo']] <- percent.ribo
VlnPlot(object = HB6, features = c("nFeature_RNA", "nCount_RNA", "percent.mito", "percent.ribo"), ncol = 4)
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.

# The number of genes and UMIs (nGene and nUMI) are automatically calculated
# for every object by Seurat.  For non-UMI data, nUMI represents the sum of
# the non-normalized values within a cell We calculate the percentage of
# mitochondrial genes here and store it in percent.mito using AddMetaData.
# We use object@raw.data since this represents non-transformed and
# non-log-normalized counts The % of UMI mapping to MT-genes is a common
# scRNA-seq QC metric.
mito.features <- grep(pattern = "^MT-", x = rownames(x = HB7), value = TRUE)
percent.mito <- Matrix::colSums(x = GetAssayData(object = HB7, slot = 'counts')[mito.features, ]) / Matrix::colSums(x = GetAssayData(object = HB7, slot = 'counts'))
# The [[ operator can add columns to object metadata, and is a great place to stash QC stats
HB7[['percent.mito']] <- percent.mito
rb.genes <- rownames(HB7)[grep("^RP[SL]",rownames(HB7))]
percent.ribo <- Matrix::colSums(x = GetAssayData(object = HB7, slot = 'counts')[rb.genes, ]) / Matrix::colSums(x = GetAssayData(object = HB7, slot = 'counts'))
HB7[['percent.ribo']] <- percent.ribo
VlnPlot(object = HB7, features = c("nFeature_RNA", "nCount_RNA", "percent.mito", "percent.ribo"), ncol = 4)
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.

# The number of genes and UMIs (nGene and nUMI) are automatically calculated
# for every object by Seurat.  For non-UMI data, nUMI represents the sum of
# the non-normalized values within a cell We calculate the percentage of
# mitochondrial genes here and store it in percent.mito using AddMetaData.
# We use object@raw.data since this represents non-transformed and
# non-log-normalized counts The % of UMI mapping to MT-genes is a common
# scRNA-seq QC metric.
mito.features <- grep(pattern = "^MT-", x = rownames(x = HB12), value = TRUE)
percent.mito <- Matrix::colSums(x = GetAssayData(object = HB12, slot = 'counts')[mito.features, ]) / Matrix::colSums(x = GetAssayData(object = HB12, slot = 'counts'))
# The [[ operator can add columns to object metadata, and is a great place to stash QC stats
HB12[['percent.mito']] <- percent.mito
rb.genes <- rownames(HB12)[grep("^RP[SL]",rownames(HB12))]
percent.ribo <- Matrix::colSums(x = GetAssayData(object = HB12, slot = 'counts')[rb.genes, ]) / Matrix::colSums(x = GetAssayData(object = HB12, slot = 'counts'))
HB12[['percent.ribo']] <- percent.ribo
VlnPlot(object = HB12, features = c("nFeature_RNA", "nCount_RNA", "percent.mito", "percent.ribo"), ncol = 4)
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.

# The number of genes and UMIs (nGene and nUMI) are automatically calculated
# for every object by Seurat.  For non-UMI data, nUMI represents the sum of
# the non-normalized values within a cell We calculate the percentage of
# mitochondrial genes here and store it in percent.mito using AddMetaData.
# We use object@raw.data since this represents non-transformed and
# non-log-normalized counts The % of UMI mapping to MT-genes is a common
# scRNA-seq QC metric.
mito.features <- grep(pattern = "^MT-", x = rownames(x = HB13), value = TRUE)
percent.mito <- Matrix::colSums(x = GetAssayData(object = HB13, slot = 'counts')[mito.features, ]) / Matrix::colSums(x = GetAssayData(object = HB13, slot = 'counts'))
# The [[ operator can add columns to object metadata, and is a great place to stash QC stats
HB13[['percent.mito']] <- percent.mito
rb.genes <- rownames(HB13)[grep("^RP[SL]",rownames(HB13))]
percent.ribo <- Matrix::colSums(x = GetAssayData(object = HB13, slot = 'counts')[rb.genes, ]) / Matrix::colSums(x = GetAssayData(object = HB13, slot = 'counts'))
HB13[['percent.ribo']] <- percent.ribo
VlnPlot(object = HB13, features = c("nFeature_RNA", "nCount_RNA", "percent.mito", "percent.ribo"), ncol = 4)
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.

# The number of genes and UMIs (nGene and nUMI) are automatically calculated
# for every object by Seurat.  For non-UMI data, nUMI represents the sum of
# the non-normalized values within a cell We calculate the percentage of
# mitochondrial genes here and store it in percent.mito using AddMetaData.
# We use object@raw.data since this represents non-transformed and
# non-log-normalized counts The % of UMI mapping to MT-genes is a common
# scRNA-seq QC metric.
mito.features <- grep(pattern = "^MT-", x = rownames(x = HB14), value = TRUE)
percent.mito <- Matrix::colSums(x = GetAssayData(object = HB14, slot = 'counts')[mito.features, ]) / Matrix::colSums(x = GetAssayData(object = HB14, slot = 'counts'))
# The [[ operator can add columns to object metadata, and is a great place to stash QC stats
HB14[['percent.mito']] <- percent.mito
rb.genes <- rownames(HB14)[grep("^RP[SL]",rownames(HB14))]
percent.ribo <- Matrix::colSums(x = GetAssayData(object = HB14, slot = 'counts')[rb.genes, ]) / Matrix::colSums(x = GetAssayData(object = HB14, slot = 'counts'))
HB14[['percent.ribo']] <- percent.ribo
VlnPlot(object = HB14, features = c("nFeature_RNA", "nCount_RNA", "percent.mito", "percent.ribo"), ncol = 4)
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.

# The number of genes and UMIs (nGene and nUMI) are automatically calculated
# for every object by Seurat.  For non-UMI data, nUMI represents the sum of
# the non-normalized values within a cell We calculate the percentage of
# mitochondrial genes here and store it in percent.mito using AddMetaData.
# We use object@raw.data since this represents non-transformed and
# non-log-normalized counts The % of UMI mapping to MT-genes is a common
# scRNA-seq QC metric.
mito.features <- grep(pattern = "^MT-", x = rownames(x = HB15), value = TRUE)
percent.mito <- Matrix::colSums(x = GetAssayData(object = HB15, slot = 'counts')[mito.features, ]) / Matrix::colSums(x = GetAssayData(object = HB15, slot = 'counts'))
# The [[ operator can add columns to object metadata, and is a great place to stash QC stats
HB15[['percent.mito']] <- percent.mito
rb.genes <- rownames(HB15)[grep("^RP[SL]",rownames(HB15))]
percent.ribo <- Matrix::colSums(x = GetAssayData(object = HB15, slot = 'counts')[rb.genes, ]) / Matrix::colSums(x = GetAssayData(object = HB15, slot = 'counts'))
HB15[['percent.ribo']] <- percent.ribo
VlnPlot(object = HB15, features = c("nFeature_RNA", "nCount_RNA", "percent.mito", "percent.ribo"), ncol = 4)
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.

# The number of genes and UMIs (nGene and nUMI) are automatically calculated
# for every object by Seurat.  For non-UMI data, nUMI represents the sum of
# the non-normalized values within a cell We calculate the percentage of
# mitochondrial genes here and store it in percent.mito using AddMetaData.
# We use object@raw.data since this represents non-transformed and
# non-log-normalized counts The % of UMI mapping to MT-genes is a common
# scRNA-seq QC metric.
mito.features <- grep(pattern = "^MT-", x = rownames(x = HB16), value = TRUE)
percent.mito <- Matrix::colSums(x = GetAssayData(object = HB16, slot = 'counts')[mito.features, ]) / Matrix::colSums(x = GetAssayData(object = HB16, slot = 'counts'))
# The [[ operator can add columns to object metadata, and is a great place to stash QC stats
HB16[['percent.mito']] <- percent.mito
rb.genes <- rownames(HB16)[grep("^RP[SL]",rownames(HB16))]
percent.ribo <- Matrix::colSums(x = GetAssayData(object = HB16, slot = 'counts')[rb.genes, ]) / Matrix::colSums(x = GetAssayData(object = HB16, slot = 'counts'))
HB16[['percent.ribo']] <- percent.ribo
VlnPlot(object = HB16, features = c("nFeature_RNA", "nCount_RNA", "percent.mito", "percent.ribo"), ncol = 4)
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.

# The number of genes and UMIs (nGene and nUMI) are automatically calculated
# for every object by Seurat.  For non-UMI data, nUMI represents the sum of
# the non-normalized values within a cell We calculate the percentage of
# mitochondrial genes here and store it in percent.mito using AddMetaData.
# We use object@raw.data since this represents non-transformed and
# non-log-normalized counts The % of UMI mapping to MT-genes is a common
# scRNA-seq QC metric.
mito.features <- grep(pattern = "^MT-", x = rownames(x = HB17), value = TRUE)
percent.mito <- Matrix::colSums(x = GetAssayData(object = HB17, slot = 'counts')[mito.features, ]) / Matrix::colSums(x = GetAssayData(object = HB17, slot = 'counts'))
# The [[ operator can add columns to object metadata, and is a great place to stash QC stats
HB17[['percent.mito']] <- percent.mito
rb.genes <- rownames(HB17)[grep("^RP[SL]",rownames(HB17))]
percent.ribo <- Matrix::colSums(x = GetAssayData(object = HB17, slot = 'counts')[rb.genes, ]) / Matrix::colSums(x = GetAssayData(object = HB17, slot = 'counts'))
HB17[['percent.ribo']] <- percent.ribo
VlnPlot(object = HB17, features = c("nFeature_RNA", "nCount_RNA", "percent.mito", "percent.ribo"), ncol = 4)
Warning: Default search for "data" layer in "RNA" assay yielded no results; utilizing "counts" layer instead.

# Set up HB1 object
HB1 <- subset(x = HB1, subset = nFeature_RNA > 200 & nFeature_RNA < 10000 & percent.mito < 0.15)

# Set up HB4 object
HB4 <- subset(x = HB4, subset = nFeature_RNA > 200 & nFeature_RNA < 10000 & percent.mito < 0.15)

# Set up HB6 object
HB6 <- subset(x = HB6, subset = nFeature_RNA > 200 & nFeature_RNA < 10000 & percent.mito < 0.15)

# Set up HB7 object
HB7 <- subset(x = HB7, subset = nFeature_RNA > 200 & nFeature_RNA < 10000 & percent.mito < 0.15)

# Set up HB12 object
HB12 <- subset(x = HB12, subset = nFeature_RNA > 200 & nFeature_RNA < 10000 & percent.mito < 0.15)

# Set up HB13 object
HB13 <- subset(x = HB13, subset = nFeature_RNA > 200 & nFeature_RNA < 10000 & percent.mito < 0.15)

# Set up HB14 object
HB14 <- subset(x = HB14, subset = nFeature_RNA > 200 & nFeature_RNA < 10000 & percent.mito < 0.15)

# Set up HB15 object
HB15 <- subset(x = HB15, subset = nFeature_RNA > 200 & nFeature_RNA < 10000 & percent.mito < 0.15)

# Set up HB16 object
HB16 <- subset(x = HB16, subset = nFeature_RNA > 200 & nFeature_RNA < 10000 & percent.mito < 0.15)

# Set up HB17 object
HB17 <- subset(x = HB17, subset = nFeature_RNA > 200 & nFeature_RNA < 10000 & percent.mito < 0.15)
HB1 <- NormalizeData(HB1)
Normalizing layer: counts
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB1 <- FindVariableFeatures(HB1, selection.method = "vst", nfeatures = 2000)
Finding variable features for layer counts
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB4 <- NormalizeData(HB4)
Normalizing layer: counts
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB4 <- FindVariableFeatures(HB4, selection.method = "vst", nfeatures = 2000)
Finding variable features for layer counts
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB6 <- NormalizeData(HB6)
Normalizing layer: counts
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB6 <- FindVariableFeatures(HB6, selection.method = "vst", nfeatures = 2000)
Finding variable features for layer counts
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB7 <- NormalizeData(HB7)
Normalizing layer: counts
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB7 <- FindVariableFeatures(HB7, selection.method = "vst", nfeatures = 2000)
Finding variable features for layer counts
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB12 <- NormalizeData(HB12)
Normalizing layer: counts
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB12 <- FindVariableFeatures(HB12, selection.method = "vst", nfeatures = 2000)
Finding variable features for layer counts
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB13 <- NormalizeData(HB13)
Normalizing layer: counts
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB13 <- FindVariableFeatures(HB13, selection.method = "vst", nfeatures = 2000)
Finding variable features for layer counts
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB14 <- NormalizeData(HB14)
Normalizing layer: counts
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB14 <- FindVariableFeatures(HB14, selection.method = "vst", nfeatures = 2000)
Finding variable features for layer counts
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB15 <- NormalizeData(HB15)
Normalizing layer: counts
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB15 <- FindVariableFeatures(HB15, selection.method = "vst", nfeatures = 2000)
Finding variable features for layer counts
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB16 <- NormalizeData(HB16)
Normalizing layer: counts
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB16 <- FindVariableFeatures(HB16, selection.method = "vst", nfeatures = 2000)
Finding variable features for layer counts
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB17 <- NormalizeData(HB17)
Normalizing layer: counts
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB17 <- FindVariableFeatures(HB17, selection.method = "vst", nfeatures = 2000)
Finding variable features for layer counts
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
HB1 <- AddMetaData(HB1, metadata="A", col.name="HB")
HB4 <- AddMetaData(HB4, metadata="B", col.name="HB")
HB6 <- AddMetaData(HB6, metadata="C", col.name="HB")
HB7 <- AddMetaData(HB7, metadata="D", col.name="HB")
HB12 <- AddMetaData(HB12, metadata="E", col.name="HB")
HB13 <- AddMetaData(HB13, metadata="F", col.name="HB")
HB14 <- AddMetaData(HB14, metadata="G", col.name="HB")
HB15 <- AddMetaData(HB15, metadata="H", col.name="HB")
HB16 <- AddMetaData(HB16, metadata="I", col.name="HB")
HB17 <- AddMetaData(HB17, metadata="J", col.name="HB")
HBbig.list <- list(HB1, HB4, HB6, HB7, HB12, HB13, HB14, HB15, HB16, HB17) 
features <- SelectIntegrationFeatures(object.list = HBbig.list)
HB.anchors <- FindIntegrationAnchors(object.list = HBbig.list, anchor.features = features)
Warning: Some cell names are duplicated across objects provided. Renaming to enforce unique cell names.Scaling features for provided objects

  |                                                  | 0 % ~calculating  
  |+++++                                             | 10% ~03s          
  |++++++++++                                        | 20% ~03s          
  |+++++++++++++++                                   | 30% ~03s          
  |++++++++++++++++++++                              | 40% ~03s          
  |+++++++++++++++++++++++++                         | 50% ~02s          
  |++++++++++++++++++++++++++++++                    | 60% ~01s          
  |+++++++++++++++++++++++++++++++++++               | 70% ~01s          
  |++++++++++++++++++++++++++++++++++++++++          | 80% ~01s          
  |+++++++++++++++++++++++++++++++++++++++++++++     | 90% ~00s          
  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=03s  
Finding all pairwise anchors

  |                                                  | 0 % ~calculating  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 15330 anchors
Filtering anchors
    Retained 852 anchors

  |++                                                | 2 % ~02h 11m 02s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 11964 anchors
Filtering anchors
    Retained 1125 anchors

  |+++                                               | 4 % ~01h 41m 39s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 12869 anchors
Filtering anchors
    Retained 5233 anchors

  |++++                                              | 7 % ~02h 16m 06s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 15112 anchors
Filtering anchors
    Retained 2234 anchors

  |+++++                                             | 9 % ~05h 21m 19s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 17375 anchors
Filtering anchors
    Retained 5782 anchors

  |++++++                                            | 11% ~07h 10m 17s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 12929 anchors
Filtering anchors
    Retained 4177 anchors

  |+++++++                                           | 13% ~06h 08m 53s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 8823 anchors
Filtering anchors
    Retained 3033 anchors

  |++++++++                                          | 16% ~05h 13m 42s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 9314 anchors
Filtering anchors
    Retained 2724 anchors

  |+++++++++                                         | 18% ~04h 35m 58s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 8407 anchors
Filtering anchors
    Retained 2565 anchors

  |++++++++++                                        | 20% ~04h 02m 46s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 9194 anchors
Filtering anchors
    Retained 4384 anchors

  |++++++++++++                                      | 22% ~03h 39m 16s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 10113 anchors
Filtering anchors
    Retained 1410 anchors

  |+++++++++++++                                     | 24% ~03h 17m 41s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 11350 anchors
Filtering anchors
    Retained 2593 anchors

  |++++++++++++++                                    | 27% ~03h 02m 34s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 9320 anchors
Filtering anchors
    Retained 3586 anchors

  |+++++++++++++++                                   | 29% ~02h 46m 33s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 11471 anchors
Filtering anchors
    Retained 2469 anchors

  |++++++++++++++++                                  | 31% ~02h 35m 27s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 7356 anchors
Filtering anchors
    Retained 1361 anchors

  |+++++++++++++++++                                 | 33% ~02h 21m 44s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 13723 anchors
Filtering anchors
    Retained 2748 anchors

  |++++++++++++++++++                                | 36% ~02h 11m 46s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 16190 anchors
Filtering anchors
    Retained 2541 anchors

  |+++++++++++++++++++                               | 38% ~02h 05m 29s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 12306 anchors
Filtering anchors
    Retained 2490 anchors

  |++++++++++++++++++++                              | 40% ~01h 56m 59s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 15530 anchors
Filtering anchors
    Retained 4684 anchors

  |++++++++++++++++++++++                            | 42% ~01h 51m 42s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 8753 anchors
Filtering anchors
    Retained 2617 anchors

  |+++++++++++++++++++++++                           | 44% ~01h 43m 10s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 10615 anchors
Filtering anchors
    Retained 2483 anchors

  |++++++++++++++++++++++++                          | 47% ~01h 35m 47s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 9853 anchors
Filtering anchors
    Retained 2093 anchors

  |+++++++++++++++++++++++++                         | 49% ~01h 28m 50s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 10552 anchors
Filtering anchors
    Retained 3120 anchors

  |++++++++++++++++++++++++++                        | 51% ~01h 23m 20s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 9165 anchors
Filtering anchors
    Retained 3685 anchors

  |+++++++++++++++++++++++++++                       | 53% ~01h 17m 13s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 10302 anchors
Filtering anchors
    Retained 5874 anchors

  |++++++++++++++++++++++++++++                      | 56% ~01h 12m 23s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 7099 anchors
Filtering anchors
    Retained 2353 anchors

  |+++++++++++++++++++++++++++++                     | 58% ~01h 06m 34s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 8095 anchors
Filtering anchors
    Retained 3538 anchors

  |++++++++++++++++++++++++++++++                    | 60% ~01h 01m 15s  
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 10017 anchors
Filtering anchors
    Retained 2584 anchors

  |++++++++++++++++++++++++++++++++                  | 62% ~56m 32s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 9602 anchors
Filtering anchors
    Retained 2918 anchors

  |+++++++++++++++++++++++++++++++++                 | 64% ~52m 01s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 10774 anchors
Filtering anchors
    Retained 2359 anchors

  |++++++++++++++++++++++++++++++++++                | 67% ~48m 15s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 9160 anchors
Filtering anchors
    Retained 2575 anchors

  |+++++++++++++++++++++++++++++++++++               | 69% ~44m 07s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 10477 anchors
Filtering anchors
    Retained 4489 anchors

  |++++++++++++++++++++++++++++++++++++              | 71% ~40m 37s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 6997 anchors
Filtering anchors
    Retained 2476 anchors

  |+++++++++++++++++++++++++++++++++++++             | 73% ~36m 35s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 7940 anchors
Filtering anchors
    Retained 2744 anchors

  |++++++++++++++++++++++++++++++++++++++            | 76% ~32m 49s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 9826 anchors
Filtering anchors
    Retained 1899 anchors

  |+++++++++++++++++++++++++++++++++++++++           | 78% ~29m 20s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 7564 anchors
Filtering anchors
    Retained 2770 anchors

  |++++++++++++++++++++++++++++++++++++++++          | 80% ~25m 51s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 5830 anchors
Filtering anchors
    Retained 2276 anchors

  |++++++++++++++++++++++++++++++++++++++++++        | 82% ~22m 29s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 5818 anchors
Filtering anchors
    Retained 2613 anchors

  |+++++++++++++++++++++++++++++++++++++++++++       | 84% ~19m 23s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 5534 anchors
Filtering anchors
    Retained 2733 anchors

  |++++++++++++++++++++++++++++++++++++++++++++      | 87% ~16m 17s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 5891 anchors
Filtering anchors
    Retained 4267 anchors

  |+++++++++++++++++++++++++++++++++++++++++++++     | 89% ~13m 23s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 4675 anchors
Filtering anchors
    Retained 2188 anchors

  |++++++++++++++++++++++++++++++++++++++++++++++    | 91% ~10m 29s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 5289 anchors
Filtering anchors
    Retained 3146 anchors

  |+++++++++++++++++++++++++++++++++++++++++++++++   | 93% ~07m 43s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 5730 anchors
Filtering anchors
    Retained 1875 anchors

  |++++++++++++++++++++++++++++++++++++++++++++++++  | 96% ~05m 03s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 4996 anchors
Filtering anchors
    Retained 3309 anchors

  |+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~02m 29s      
Running CCA
Merging objects
Finding neighborhoods
Finding anchors
    Found 5018 anchors
Filtering anchors
    Retained 3013 anchors

  |++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed=01h 49m 24s
# this command creates an 'integrated' data assay
HB.combined <- IntegrateData(anchorset = HB.anchors)
Merging dataset 10 into 4
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Merging dataset 8 into 4 10
Extracting anchors for merged samples
Finding integration vectors
Warning: Different cells in new layer data than already exists for scale.dataFinding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Merging dataset 5 into 1
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Merging dataset 3 into 2
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Merging dataset 9 into 1 5
Extracting anchors for merged samples
Finding integration vectors
Warning: Different cells in new layer data than already exists for scale.dataFinding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Merging dataset 7 into 4 10 8
Extracting anchors for merged samples
Finding integration vectors
Warning: Different cells in new layer data than already exists for scale.dataFinding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Merging dataset 6 into 2 3
Extracting anchors for merged samples
Finding integration vectors
Warning: Different cells in new layer data than already exists for scale.dataFinding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Merging dataset 2 3 6 into 4 10 8 7
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
Merging dataset 1 5 9 into 4 10 8 7 2 3 6
Extracting anchors for merged samples
Finding integration vectors
Finding integration vector weights
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Integrating data
# specify that we will perform downstream analysis on the corrected data note that the original
# unmodified data still resides in the 'RNA' assay
DefaultAssay(HB.combined) <- "integrated"

# Run the standard workflow for visualization and clustering
HB.combined <- ScaleData(HB.combined, vars.to.regress = c("nCount_RNA", "percent.mito", "percent.ribo"), verbose = FALSE)
HB.combined <- RunPCA(HB.combined, verbose = FALSE)
HB.combined <- RunUMAP(HB.combined, reduction = "pca", dims = 1:30, set.seed(123))
Warning: The default method for RunUMAP has changed from calling Python UMAP via reticulate to the R-native UWOT using the cosine metric
To use Python UMAP via reticulate, set umap.method to 'umap-learn' and metric to 'correlation'
This message will be shown once per session16:49:05 UMAP embedding parameters a = 0.9922 b = 1.112
Found more than one class "dist" in cache; using the first, from namespace 'BiocGenerics'
Also defined by ‘spam’
16:49:05 Read 40666 rows and found 30 numeric columns
16:49:05 Using Annoy for neighbor search, n_neighbors = 30
Found more than one class "dist" in cache; using the first, from namespace 'BiocGenerics'
Also defined by ‘spam’
16:49:05 Building Annoy index with metric = cosine, n_trees = 50
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
16:49:08 Writing NN index file to temp file /var/folders/4q/4mb5qhz51qdgffngk4lqzs540000gn/T//RtmpE16bnd/file4201267475d
16:49:09 Searching Annoy index using 1 thread, search_k = 3000
16:49:22 Annoy recall = 100%
16:49:24 Commencing smooth kNN distance calibration using 1 thread with target n_neighbors = 30
16:49:25 Initializing from normalized Laplacian + noise (using RSpectra)
16:49:26 Commencing optimization for 200 epochs, with 1868092 positive edges
Using method 'umap'
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
16:49:48 Optimization finished
HB.combined <- FindNeighbors(HB.combined, reduction = "pca", dims = 1:30)
Computing nearest neighbor graph
Computing SNN
HB.combined <- FindClusters(HB.combined, resolution = 0.4)
Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck

Number of nodes: 40666
Number of edges: 1494520

Running Louvain algorithm...
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.8948
Number of communities: 12
Elapsed time: 14 seconds
# Visualization
DimPlot(HB.combined, reduction = "umap", label = TRUE, repel = TRUE)

DimPlot(HB.combined, reduction = "umap", split.by = "HB", ncol = 4)

# How do I create a UMAP plot where cells are colored by replicate?  First, store the current
# identities in a new column of meta.data called CellType
HB.combined$CellType <- Idents(HB.combined)
# Next, switch the identity class of all cells to reflect replicate ID
Idents(HB.combined) <- "seurat_clusters"
DimPlot(HB.combined, reduction = "umap", label = TRUE)

<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxucDIgPC0gRGltUGxvdChIQi5jb21iaW5lZCwgcmVkdWN0aW9uID0gXCJ1bWFwXCIsIGxhYmVsID0gVFJVRSwgcmVwZWwgPSBUUlVFKVxucDJcbmBgYCJ9 -->

```r
p2 <- DimPlot(HB.combined, reduction = "umap", label = TRUE, repel = TRUE)
p2
saveRDS(HB.combined, file = "/Users/pengwu/Documents/Experiments/scRNAseq/HBcombined.rds")
DimPlot(object = HB.combined, reduction = 'umap', split.by = "HB", width = 2000, height = 1500, units = "px", res = 300)
tiff(file = "/Volumes/backups/Peng/Research/scRNAseq/HBcombined.tiff", width = 2000, height = 1500, units = "px", res = 300)
dev.off()
# For performing differential expression after integration, we switch back to the original data
DefaultAssay(HB.combined) <- "RNA"
AllClust.markers <- FindAllMarkers(HB.combined, grouping.var = "HB", verbose = FALSE)
write.csv(AllClust.markers,"/Users/pengwu/Documents/Experiments/scRNAseq/allclusters.csv",row.names = TRUE)
cluster0.markers <- FindConservedMarkers(HB.combined, ident.1 = 0, grouping.var = "HB", verbose = FALSE)
write.csv(cluster0.markers,"/Users/pengwu/Documents/Experiments/scRNAseq/cluster0.csv",row.names = TRUE)
cluster1.markers <- FindConservedMarkers(HB.combined, ident.1 = 1, grouping.var = "HB", verbose = FALSE)
write.csv(cluster1.markers,"/Users/pengwu/Documents/Experiments/scRNAseq/cluster1.csv",row.names = TRUE)
cluster2.markers <- FindConservedMarkers(HB.combined, ident.1 = 2, grouping.var = "HB", verbose = FALSE)
write.csv(cluster2.markers,"/Users/pengwu/Documents/Experiments/scRNAseq/cluster2.csv",row.names = TRUE)
cluster3.markers <- FindConservedMarkers(HB.combined, ident.1 = 3, grouping.var = "HB", verbose = FALSE)
write.csv(cluster3.markers,"/Users/pengwu/Documents/Experiments/scRNAseq/cluster3.csv",row.names = TRUE)
cluster4.markers <- FindConservedMarkers(HB.combined, ident.1 = 4, grouping.var = "HB", verbose = FALSE)
write.csv(cluster4.markers,"/Users/pengwu/Documents/Experiments/scRNAseq/cluster4.csv",row.names = TRUE)
cluster5.markers <- FindConservedMarkers(HB.combined, ident.1 = 5, grouping.var = "HB", verbose = FALSE)
write.csv(cluster5.markers,"/Users/pengwu/Documents/Experiments/scRNAseq/cluster5.csv",row.names = TRUE)
cluster6.markers <- FindConservedMarkers(HB.combined, ident.1 = 6, grouping.var = "HB", verbose = FALSE)
write.csv(cluster6.markers,"/Users/pengwu/Documents/Experiments/scRNAseq/cluster6.csv",row.names = TRUE)
cluster7.markers <- FindConservedMarkers(HB.combined, ident.1 =7, grouping.var = "HB", verbose = FALSE)
write.csv(cluster7.markers,"/Users/pengwu/Documents/Experiments/scRNAseq/cluster7.csv",row.names = TRUE)
cluster8.markers <- FindConservedMarkers(HB.combined, ident.1 =8, grouping.var = "HB", verbose = FALSE)
write.csv(cluster8.markers,"/Users/pengwu/Documents/Experiments/scRNAseq/cluster8.csv",row.names = TRUE)
cluster9.markers <- FindConservedMarkers(HB.combined, ident.1 =9, grouping.var = "HB", verbose = FALSE)
write.csv(cluster9.markers,"/Users/pengwu/Documents/Experiments/scRNAseq/cluster9.csv",row.names = TRUE)
cluster10.markers <- FindConservedMarkers(HB.combined, ident.1 = 10, grouping.var = "HB", verbose = FALSE)
write.csv(cluster10.markers,"/Users/pengwu/Documents/Experiments/scRNAseq/cluster10.csv",row.names = TRUE)
cluster11.markers <- FindConservedMarkers(HB.combined, ident.1 = 11, grouping.var = "HB", verbose = FALSE)
write.csv(cluster11.markers,"/Users/pengwu/Documents/Experiments/scRNAseq/cluster11.csv",row.names = TRUE)
# Example for plotting gene features
FeaturePlot(object = HB.combined, features = c("FGF19", "KLB", "FGFR4"))
tiff(file = "FGF.tiff", width = 1500, height = 1500, units = "px", res = 300)
dev.off()
# Example for calculating gene signatures
FetvNorm <- read.csv('/Users/pengwu/Documents/Experiments/RNAseq/180805Final/FetvNorm_Top50.csv', header=F, sep=",")
FetvNorm <- as.matrix(FetvNorm)
HB.combined <- AddModuleScore(HB.combined,
                  features = list(FetvNorm),
                  name="FetvNorm")
# Plot scores
FeaturePlot(HB.combined,
            features = c("FetvNorm1"), label = FALSE, repel = TRUE) +
            scale_colour_gradientn(colours = rev(brewer.pal(n = 11, name = "RdBu")))
# Example for violin plots
my_genes <- HB.combined[row.names(subset(fData(HB.combined), gene_short_name %in% c("AFP", "HNF4A", "KRT19", "SOX4"))),]

tiff(file = "AFPGenes_Violin.tiff", width = 1500, height = 1500, units = "px", res = 300)
p <- plot_genes_violin(my_genes, grouping = "cluster", ncol=2, min_expr=0.1,
  color_by = "cluster")
p + geom_jitter(shape=16, position=position_jitter(0.2))
dev.off()
# Dot plots - the size of the dot corresponds to the percentage of cells expressing the
# feature in each cluster. The color represents the average expression level
features.plot <- c("FGF1", "FGF2", "FGF3", "FGF4", "FGF7", "FGF8", "FGF9", "FGF10", "FGF11", "FGF12", "FGF13", "FGF14", "FGF17", "FGF18", "FGF19", "FGF20", "FGF21", "FGF22", "FGF23")
DotPlot(HB.combined, features = features.plot, group.by = "HB") + RotatedAxis()
# Dot plots - the size of the dot corresponds to the percentage of cells expressing the
# feature in each cluster. The color represents the average expression level
features.plot <- c("FGFR1", "FGFR2", "FGFR3", "FGFR4", "KLB", "EGFR", "MET", "IGF1R", "IGF2R", "INSR", "EGF", "HGF", "IGF1", "IGF2.1")
DotPlot(HB.combined, features = features.plot, group.by = "HB") + RotatedAxis()
umapCoord <- as.data.frame(Embeddings(object = HB.combined[["umap"]]))
umapCoordmat <- as.matrix(umapCoord)
# Monocle for pseudotime analyses
remotes::install_github('satijalab/seurat-wrappers')
library(monocle3)
library(Seurat)
library(SeuratWrappers)
library(patchwork)
library(dplyr)

set.seed(1234)
HB.monocle <- as.cell_data_set(HB.combined)
HB.monocle <- cluster_cells(HB.monocle, cluster_method = "louvain")

p1 <- plot_cells(HB.monocle, color_cells_by = "cluster", show_trajectory_graph = FALSE)
p2 <- plot_cells(HB.monocle, color_cells_by = "partition", show_trajectory_graph = FALSE)
wrap_plots(p1, p2)
integrated.sub <- subset(as.Seurat(HB.monocle, assay = NULL), monocle3_partitions == 1)
HB.monocle <- as.cell_data_set(integrated.sub)
HB.monocle <- learn_graph(HB.monocle, use_partition = TRUE, verbose = FALSE)
plot_cells(HB.monocle,
           color_cells_by = "cluster",
           label_groups_by_cluster=FALSE,
           label_leaves=FALSE,
           label_branch_points=FALSE)
HB.monocle <- order_cells(HB.monocle, root_cells = colnames(HB.monocle[,clusters(HB.monocle) == 47]))
plot_cells(HB.monocle,
           color_cells_by = "pseudotime",
           group_cells_by = "cluster",
           label_cell_groups = FALSE,
           label_groups_by_cluster=FALSE,
           label_leaves=FALSE,
           label_branch_points=FALSE,
           label_roots = FALSE,
           trajectory_graph_color = "grey60")

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Cmd+Option+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Cmd+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tCnRpdGxlOiAiU2V1cmF0IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKLS0tCgpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiAKClRyeSBleGVjdXRpbmcgdGhpcyBjaHVuayBieSBjbGlja2luZyB0aGUgKlJ1biogYnV0dG9uIHdpdGhpbiB0aGUgY2h1bmsgb3IgYnkgcGxhY2luZyB5b3VyIGN1cnNvciBpbnNpZGUgaXQgYW5kIHByZXNzaW5nICpDbWQrU2hpZnQrRW50ZXIqLiAKCmBgYHtyfQppbnN0YWxsLnBhY2thZ2VzKCdkZXZ0b29scycpCmluc3RhbGwucGFja2FnZXMoJ1NldXJhdCcpCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShnZ3Bsb3QyKQpgYGAKCmBgYHtyfQojTG9hZGluZyBtYXRyaWNlcyBmcm9tIGNlbGxyYW5nZXIgb3V0cHV0CmxpYnJhcnkoTWF0cml4KQptYXRyaXhfZGlyID0gIi9Vc2Vycy9wZW5nd3UvRG9jdW1lbnRzL1Jlc2VhcmNoIC0gT2xkL3NjUk5Bc2VxL0hCMS1KYW4yMDE5L2ZpbHRlcmVkX2ZlYXR1cmVfYmNfbWF0cml4LyIKYmFyY29kZS5wYXRoIDwtIHBhc3RlMChtYXRyaXhfZGlyLCAiSEIxX2JhcmNvZGVzLnRzdi5neiIpCmZlYXR1cmVzLnBhdGggPC0gcGFzdGUwKG1hdHJpeF9kaXIsICJIQjFfZmVhdHVyZXMudHN2Lmd6IikKbWF0cml4LnBhdGggPC0gcGFzdGUwKG1hdHJpeF9kaXIsICJIQjFfbWF0cml4Lm10eC5neiIpCm1hdCA8LSByZWFkTU0oZmlsZSA9IG1hdHJpeC5wYXRoKQpmZWF0dXJlLm5hbWVzID0gcmVhZC5kZWxpbShmZWF0dXJlcy5wYXRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKYmFyY29kZS5uYW1lcyA9IHJlYWQuZGVsaW0oYmFyY29kZS5wYXRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKY29sbmFtZXMobWF0KSA9IGJhcmNvZGUubmFtZXMkVjEKcm93bmFtZXMobWF0KSA9IG1ha2UudW5pcXVlKGZlYXR1cmUubmFtZXMkVjIpCmBgYApgYGB7cn0KIyBJbml0aWFsaXplIHRoZSBTZXVyYXQgb2JqZWN0IHdpdGggdGhlIHJhdyAobm9uLW5vcm1hbGl6ZWQgZGF0YSkuICBLZWVwIGFsbAojIGdlbmVzIGV4cHJlc3NlZCBpbiA+PSAzIGNlbGxzICh+MC4xJSBvZiB0aGUgZGF0YSkuIEtlZXAgYWxsIGNlbGxzIHdpdGggYXQKIyBsZWFzdCAyMDAgZGV0ZWN0ZWQgZ2VuZXMKSEIxIDwtIENyZWF0ZVNldXJhdE9iamVjdChjb3VudHMgPSBtYXQsIG1pbi5jZWxscyA9IDMsIG1pbi5mZWF0dXJlcyA9IDIwMCwgcHJvamVjdCA9ICJIQjEiKQpIQjEKYGBgCgpgYGB7cn0KI0xvYWRpbmcgbWF0cmljZXMgZnJvbSBjZWxscmFuZ2VyIG91dHB1dApsaWJyYXJ5KE1hdHJpeCkKbWF0cml4X2RpciA9ICIvVXNlcnMvcGVuZ3d1L0RvY3VtZW50cy9SZXNlYXJjaCAtIE9sZC9zY1JOQXNlcS9IQjQtT2N0MjAyMC9vdXRzL2ZpbHRlcmVkX2ZlYXR1cmVfYmNfbWF0cml4LyIKYmFyY29kZS5wYXRoIDwtIHBhc3RlMChtYXRyaXhfZGlyLCAiSEI0X2JhcmNvZGVzLnRzdi5neiIpCmZlYXR1cmVzLnBhdGggPC0gcGFzdGUwKG1hdHJpeF9kaXIsICJIQjRfZmVhdHVyZXMudHN2Lmd6IikKbWF0cml4LnBhdGggPC0gcGFzdGUwKG1hdHJpeF9kaXIsICJIQjRfbWF0cml4Lm10eC5neiIpCm1hdCA8LSByZWFkTU0oZmlsZSA9IG1hdHJpeC5wYXRoKQpmZWF0dXJlLm5hbWVzID0gcmVhZC5kZWxpbShmZWF0dXJlcy5wYXRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKYmFyY29kZS5uYW1lcyA9IHJlYWQuZGVsaW0oYmFyY29kZS5wYXRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKY29sbmFtZXMobWF0KSA9IGJhcmNvZGUubmFtZXMkVjEKcm93bmFtZXMobWF0KSA9IG1ha2UudW5pcXVlKGZlYXR1cmUubmFtZXMkVjIpCmBgYAoKYGBge3J9CiMgSW5pdGlhbGl6ZSB0aGUgU2V1cmF0IG9iamVjdCB3aXRoIHRoZSByYXcgKG5vbi1ub3JtYWxpemVkIGRhdGEpLiAgS2VlcCBhbGwKIyBnZW5lcyBleHByZXNzZWQgaW4gPj0gMyBjZWxscyAofjAuMSUgb2YgdGhlIGRhdGEpLiBLZWVwIGFsbCBjZWxscyB3aXRoIGF0CiMgbGVhc3QgMjAwIGRldGVjdGVkIGdlbmVzCkhCNCA8LSBDcmVhdGVTZXVyYXRPYmplY3QoY291bnRzID0gbWF0LCBtaW4uY2VsbHMgPSAzLCBtaW4uZmVhdHVyZXMgPSAyMDAsIHByb2plY3QgPSAiSEI0IikKSEI0CmBgYAoKYGBge3J9Cm1hdHJpeF9kaXIgPSAiL1VzZXJzL3Blbmd3dS9Eb2N1bWVudHMvUmVzZWFyY2ggLSBPbGQvc2NSTkFzZXEvSEI2LU9jdDIwMjAvb3V0cy9maWx0ZXJlZF9mZWF0dXJlX2JjX21hdHJpeC8iCmJhcmNvZGUucGF0aCA8LSBwYXN0ZTAobWF0cml4X2RpciwgIkhCNl9iYXJjb2Rlcy50c3YuZ3oiKQpmZWF0dXJlcy5wYXRoIDwtIHBhc3RlMChtYXRyaXhfZGlyLCAiSEI2X2ZlYXR1cmVzLnRzdi5neiIpCm1hdHJpeC5wYXRoIDwtIHBhc3RlMChtYXRyaXhfZGlyLCAiSEI2X21hdHJpeC5tdHguZ3oiKQptYXQgPC0gcmVhZE1NKGZpbGUgPSBtYXRyaXgucGF0aCkKZmVhdHVyZS5uYW1lcyA9IHJlYWQuZGVsaW0oZmVhdHVyZXMucGF0aCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCmJhcmNvZGUubmFtZXMgPSByZWFkLmRlbGltKGJhcmNvZGUucGF0aCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCmNvbG5hbWVzKG1hdCkgPSBiYXJjb2RlLm5hbWVzJFYxCnJvd25hbWVzKG1hdCkgPSBtYWtlLnVuaXF1ZShmZWF0dXJlLm5hbWVzJFYyKQpgYGAKCmBgYHtyfQojIEluaXRpYWxpemUgdGhlIFNldXJhdCBvYmplY3Qgd2l0aCB0aGUgcmF3IChub24tbm9ybWFsaXplZCBkYXRhKS4gIEtlZXAgYWxsCiMgZ2VuZXMgZXhwcmVzc2VkIGluID49IDMgY2VsbHMgKH4wLjElIG9mIHRoZSBkYXRhKS4gS2VlcCBhbGwgY2VsbHMgd2l0aCBhdAojIGxlYXN0IDIwMCBkZXRlY3RlZCBnZW5lcwpIQjYgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IG1hdCwgbWluLmNlbGxzID0gMywgbWluLmZlYXR1cmVzID0gMjAwLCBwcm9qZWN0ID0gIkhCNiIpCkhCNgpgYGAKCmBgYHtyfQptYXRyaXhfZGlyID0gIi9Vc2Vycy9wZW5nd3UvRG9jdW1lbnRzL1Jlc2VhcmNoIC0gT2xkL3NjUk5Bc2VxL0hCNy1PY3QyMDIwL291dHMvZmlsdGVyZWRfZmVhdHVyZV9iY19tYXRyaXgvIgpiYXJjb2RlLnBhdGggPC0gcGFzdGUwKG1hdHJpeF9kaXIsICJIQjdfYmFyY29kZXMudHN2Lmd6IikKZmVhdHVyZXMucGF0aCA8LSBwYXN0ZTAobWF0cml4X2RpciwgIkhCN19mZWF0dXJlcy50c3YuZ3oiKQptYXRyaXgucGF0aCA8LSBwYXN0ZTAobWF0cml4X2RpciwgIkhCN19tYXRyaXgubXR4Lmd6IikKbWF0IDwtIHJlYWRNTShmaWxlID0gbWF0cml4LnBhdGgpCmZlYXR1cmUubmFtZXMgPSByZWFkLmRlbGltKGZlYXR1cmVzLnBhdGgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQpiYXJjb2RlLm5hbWVzID0gcmVhZC5kZWxpbShiYXJjb2RlLnBhdGgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQpjb2xuYW1lcyhtYXQpID0gYmFyY29kZS5uYW1lcyRWMQpyb3duYW1lcyhtYXQpID0gbWFrZS51bmlxdWUoZmVhdHVyZS5uYW1lcyRWMikKYGBgCgpgYGB7cn0KIyBJbml0aWFsaXplIHRoZSBTZXVyYXQgb2JqZWN0IHdpdGggdGhlIHJhdyAobm9uLW5vcm1hbGl6ZWQgZGF0YSkuICBLZWVwIGFsbAojIGdlbmVzIGV4cHJlc3NlZCBpbiA+PSAzIGNlbGxzICh+MC4xJSBvZiB0aGUgZGF0YSkuIEtlZXAgYWxsIGNlbGxzIHdpdGggYXQKIyBsZWFzdCAyMDAgZGV0ZWN0ZWQgZ2VuZXMKSEI3IDwtIENyZWF0ZVNldXJhdE9iamVjdChjb3VudHMgPSBtYXQsIG1pbi5jZWxscyA9IDMsIG1pbi5mZWF0dXJlcyA9IDIwMCwgcHJvamVjdCA9ICJIQjciKQpIQjcKYGBgCmBgYHtyfQptYXRyaXhfZGlyID0gIi9Vc2Vycy9wZW5nd3UvRG9jdW1lbnRzL1Jlc2VhcmNoIC0gT2xkL3NjUk5Bc2VxL0hCMTItSnVsMjAyMS9vdXRzLyIKYmFyY29kZS5wYXRoIDwtIHBhc3RlMChtYXRyaXhfZGlyLCAiSEIxMl9iYXJjb2Rlcy50c3YuZ3oiKQpmZWF0dXJlcy5wYXRoIDwtIHBhc3RlMChtYXRyaXhfZGlyLCAiSEIxMl9mZWF0dXJlcy50c3YuZ3oiKQptYXRyaXgucGF0aCA8LSBwYXN0ZTAobWF0cml4X2RpciwgIkhCMTJfbWF0cml4Lm10eC5neiIpCm1hdCA8LSByZWFkTU0oZmlsZSA9IG1hdHJpeC5wYXRoKQpmZWF0dXJlLm5hbWVzID0gcmVhZC5kZWxpbShmZWF0dXJlcy5wYXRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKYmFyY29kZS5uYW1lcyA9IHJlYWQuZGVsaW0oYmFyY29kZS5wYXRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKY29sbmFtZXMobWF0KSA9IGJhcmNvZGUubmFtZXMkVjEKcm93bmFtZXMobWF0KSA9IG1ha2UudW5pcXVlKGZlYXR1cmUubmFtZXMkVjIpCmBgYAoKYGBge3J9CiMgSW5pdGlhbGl6ZSB0aGUgU2V1cmF0IG9iamVjdCB3aXRoIHRoZSByYXcgKG5vbi1ub3JtYWxpemVkIGRhdGEpLiAgS2VlcCBhbGwKIyBnZW5lcyBleHByZXNzZWQgaW4gPj0gMyBjZWxscyAofjAuMSUgb2YgdGhlIGRhdGEpLiBLZWVwIGFsbCBjZWxscyB3aXRoIGF0CiMgbGVhc3QgMjAwIGRldGVjdGVkIGdlbmVzCkhCMTIgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IG1hdCwgbWluLmNlbGxzID0gMywgbWluLmZlYXR1cmVzID0gMjAwLCBwcm9qZWN0ID0gIkhCMTIiKQpIQjEyCmBgYAoKYGBge3J9Cm1hdHJpeF9kaXIgPSAiL1VzZXJzL3Blbmd3dS9Eb2N1bWVudHMvUmVzZWFyY2ggLSBPbGQvc2NSTkFzZXEvSEIxMy1KdWwyMDIxL291dHMvIgpiYXJjb2RlLnBhdGggPC0gcGFzdGUwKG1hdHJpeF9kaXIsICJIQjEzX2JhcmNvZGVzLnRzdi5neiIpCmZlYXR1cmVzLnBhdGggPC0gcGFzdGUwKG1hdHJpeF9kaXIsICJIQjEzX2ZlYXR1cmVzLnRzdi5neiIpCm1hdHJpeC5wYXRoIDwtIHBhc3RlMChtYXRyaXhfZGlyLCAiSEIxM19tYXRyaXgubXR4Lmd6IikKbWF0IDwtIHJlYWRNTShmaWxlID0gbWF0cml4LnBhdGgpCmZlYXR1cmUubmFtZXMgPSByZWFkLmRlbGltKGZlYXR1cmVzLnBhdGgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQpiYXJjb2RlLm5hbWVzID0gcmVhZC5kZWxpbShiYXJjb2RlLnBhdGgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXIgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQpjb2xuYW1lcyhtYXQpID0gYmFyY29kZS5uYW1lcyRWMQpyb3duYW1lcyhtYXQpID0gbWFrZS51bmlxdWUoZmVhdHVyZS5uYW1lcyRWMikKYGBgCgpgYGB7cn0KIyBJbml0aWFsaXplIHRoZSBTZXVyYXQgb2JqZWN0IHdpdGggdGhlIHJhdyAobm9uLW5vcm1hbGl6ZWQgZGF0YSkuICBLZWVwIGFsbAojIGdlbmVzIGV4cHJlc3NlZCBpbiA+PSAzIGNlbGxzICh+MC4xJSBvZiB0aGUgZGF0YSkuIEtlZXAgYWxsIGNlbGxzIHdpdGggYXQKIyBsZWFzdCAyMDAgZGV0ZWN0ZWQgZ2VuZXMKSEIxMyA8LSBDcmVhdGVTZXVyYXRPYmplY3QoY291bnRzID0gbWF0LCBtaW4uY2VsbHMgPSAzLCBtaW4uZmVhdHVyZXMgPSAyMDAsIHByb2plY3QgPSAiSEIxMyIpCkhCMTMKYGBgCmBgYHtyfQptYXRyaXhfZGlyID0gIi9Vc2Vycy9wZW5nd3UvRG9jdW1lbnRzL1Jlc2VhcmNoIC0gT2xkL3NjUk5Bc2VxL0hCMTQtQXByMjAyMi8iCmJhcmNvZGUucGF0aCA8LSBwYXN0ZTAobWF0cml4X2RpciwgIkhCMTRfYmFyY29kZXMudHN2Lmd6IikKZmVhdHVyZXMucGF0aCA8LSBwYXN0ZTAobWF0cml4X2RpciwgIkhCMTRfZmVhdHVyZXMudHN2Lmd6IikKbWF0cml4LnBhdGggPC0gcGFzdGUwKG1hdHJpeF9kaXIsICJIQjE0X21hdHJpeC5tdHguZ3oiKQptYXQgPC0gcmVhZE1NKGZpbGUgPSBtYXRyaXgucGF0aCkKZmVhdHVyZS5uYW1lcyA9IHJlYWQuZGVsaW0oZmVhdHVyZXMucGF0aCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCmJhcmNvZGUubmFtZXMgPSByZWFkLmRlbGltKGJhcmNvZGUucGF0aCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlciA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCmNvbG5hbWVzKG1hdCkgPSBiYXJjb2RlLm5hbWVzJFYxCnJvd25hbWVzKG1hdCkgPSBtYWtlLnVuaXF1ZShmZWF0dXJlLm5hbWVzJFYyKQpgYGAKCmBgYHtyfQojIEluaXRpYWxpemUgdGhlIFNldXJhdCBvYmplY3Qgd2l0aCB0aGUgcmF3IChub24tbm9ybWFsaXplZCBkYXRhKS4gIEtlZXAgYWxsCiMgZ2VuZXMgZXhwcmVzc2VkIGluID49IDMgY2VsbHMgKH4wLjElIG9mIHRoZSBkYXRhKS4gS2VlcCBhbGwgY2VsbHMgd2l0aCBhdAojIGxlYXN0IDIwMCBkZXRlY3RlZCBnZW5lcwpIQjE0IDwtIENyZWF0ZVNldXJhdE9iamVjdChjb3VudHMgPSBtYXQsIG1pbi5jZWxscyA9IDMsIG1pbi5mZWF0dXJlcyA9IDIwMCwgcHJvamVjdCA9ICJIQjE0IikKSEIxNApgYGAKYGBge3J9Cm1hdHJpeF9kaXIgPSAiL1VzZXJzL3Blbmd3dS9Eb2N1bWVudHMvUmVzZWFyY2ggLSBPbGQvc2NSTkFzZXEvSEIxNS0yL2ZpbHRlcmVkX2ZlYXR1cmVfYmNfbWF0cml4LyIKYmFyY29kZS5wYXRoIDwtIHBhc3RlMChtYXRyaXhfZGlyLCAiSEIxNV9iYXJjb2Rlcy50c3YuZ3oiKQpmZWF0dXJlcy5wYXRoIDwtIHBhc3RlMChtYXRyaXhfZGlyLCAiSEIxNV9mZWF0dXJlcy50c3YuZ3oiKQptYXRyaXgucGF0aCA8LSBwYXN0ZTAobWF0cml4X2RpciwgIkhCMTVfbWF0cml4Lm10eC5neiIpCm1hdCA8LSByZWFkTU0oZmlsZSA9IG1hdHJpeC5wYXRoKQpmZWF0dXJlLm5hbWVzID0gcmVhZC5kZWxpbShmZWF0dXJlcy5wYXRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKYmFyY29kZS5uYW1lcyA9IHJlYWQuZGVsaW0oYmFyY29kZS5wYXRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKY29sbmFtZXMobWF0KSA9IGJhcmNvZGUubmFtZXMkVjEKcm93bmFtZXMobWF0KSA9IG1ha2UudW5pcXVlKGZlYXR1cmUubmFtZXMkVjIpCmBgYAoKYGBge3J9CiMgSW5pdGlhbGl6ZSB0aGUgU2V1cmF0IG9iamVjdCB3aXRoIHRoZSByYXcgKG5vbi1ub3JtYWxpemVkIGRhdGEpLiAgS2VlcCBhbGwKIyBnZW5lcyBleHByZXNzZWQgaW4gPj0gMyBjZWxscyAofjAuMSUgb2YgdGhlIGRhdGEpLiBLZWVwIGFsbCBjZWxscyB3aXRoIGF0CiMgbGVhc3QgMjAwIGRldGVjdGVkIGdlbmVzCkhCMTUgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IG1hdCwgbWluLmNlbGxzID0gMywgbWluLmZlYXR1cmVzID0gMjAwLCBwcm9qZWN0ID0gIkhCMTUiKQpIQjE1CmBgYApgYGB7cn0KbWF0cml4X2RpciA9ICIvVXNlcnMvcGVuZ3d1L0RvY3VtZW50cy9SZXNlYXJjaCAtIE9sZC9zY1JOQXNlcS9IQjE2L2ZpbHRlcmVkX2ZlYXR1cmVfYmNfbWF0cml4LyIKYmFyY29kZS5wYXRoIDwtIHBhc3RlMChtYXRyaXhfZGlyLCAiSEIxNl9iYXJjb2Rlcy50c3YuZ3oiKQpmZWF0dXJlcy5wYXRoIDwtIHBhc3RlMChtYXRyaXhfZGlyLCAiSEIxNl9mZWF0dXJlcy50c3YuZ3oiKQptYXRyaXgucGF0aCA8LSBwYXN0ZTAobWF0cml4X2RpciwgIkhCMTZfbWF0cml4Lm10eC5neiIpCm1hdCA8LSByZWFkTU0oZmlsZSA9IG1hdHJpeC5wYXRoKQpmZWF0dXJlLm5hbWVzID0gcmVhZC5kZWxpbShmZWF0dXJlcy5wYXRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKYmFyY29kZS5uYW1lcyA9IHJlYWQuZGVsaW0oYmFyY29kZS5wYXRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKY29sbmFtZXMobWF0KSA9IGJhcmNvZGUubmFtZXMkVjEKcm93bmFtZXMobWF0KSA9IG1ha2UudW5pcXVlKGZlYXR1cmUubmFtZXMkVjIpCmBgYAoKYGBge3J9CiMgSW5pdGlhbGl6ZSB0aGUgU2V1cmF0IG9iamVjdCB3aXRoIHRoZSByYXcgKG5vbi1ub3JtYWxpemVkIGRhdGEpLiAgS2VlcCBhbGwKIyBnZW5lcyBleHByZXNzZWQgaW4gPj0gMyBjZWxscyAofjAuMSUgb2YgdGhlIGRhdGEpLiBLZWVwIGFsbCBjZWxscyB3aXRoIGF0CiMgbGVhc3QgMjAwIGRldGVjdGVkIGdlbmVzCkhCMTYgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IG1hdCwgbWluLmNlbGxzID0gMywgbWluLmZlYXR1cmVzID0gMjAwLCBwcm9qZWN0ID0gIkhCMTYiKQpIQjE2CmBgYApgYGB7cn0KbWF0cml4X2RpciA9ICIvVXNlcnMvcGVuZ3d1L0RvY3VtZW50cy9SZXNlYXJjaCAtIE9sZC9zY1JOQXNlcS9IQjE3L2ZpbHRlcmVkX2ZlYXR1cmVfYmNfbWF0cml4LyIKYmFyY29kZS5wYXRoIDwtIHBhc3RlMChtYXRyaXhfZGlyLCAiSEIxN19iYXJjb2Rlcy50c3YuZ3oiKQpmZWF0dXJlcy5wYXRoIDwtIHBhc3RlMChtYXRyaXhfZGlyLCAiSEIxN19mZWF0dXJlcy50c3YuZ3oiKQptYXRyaXgucGF0aCA8LSBwYXN0ZTAobWF0cml4X2RpciwgIkhCMTdfbWF0cml4Lm10eC5neiIpCm1hdCA8LSByZWFkTU0oZmlsZSA9IG1hdHJpeC5wYXRoKQpmZWF0dXJlLm5hbWVzID0gcmVhZC5kZWxpbShmZWF0dXJlcy5wYXRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKYmFyY29kZS5uYW1lcyA9IHJlYWQuZGVsaW0oYmFyY29kZS5wYXRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKY29sbmFtZXMobWF0KSA9IGJhcmNvZGUubmFtZXMkVjEKcm93bmFtZXMobWF0KSA9IG1ha2UudW5pcXVlKGZlYXR1cmUubmFtZXMkVjIpCmBgYAoKYGBge3J9CiMgSW5pdGlhbGl6ZSB0aGUgU2V1cmF0IG9iamVjdCB3aXRoIHRoZSByYXcgKG5vbi1ub3JtYWxpemVkIGRhdGEpLiAgS2VlcCBhbGwKIyBnZW5lcyBleHByZXNzZWQgaW4gPj0gMyBjZWxscyAofjAuMSUgb2YgdGhlIGRhdGEpLiBLZWVwIGFsbCBjZWxscyB3aXRoIGF0CiMgbGVhc3QgMjAwIGRldGVjdGVkIGdlbmVzCkhCMTcgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IG1hdCwgbWluLmNlbGxzID0gMywgbWluLmZlYXR1cmVzID0gMjAwLCBwcm9qZWN0ID0gIkhCMTYiKQpIQjE3CmBgYApgYGB7cn0KIyBUaGUgbnVtYmVyIG9mIGdlbmVzIGFuZCBVTUlzIChuR2VuZSBhbmQgblVNSSkgYXJlIGF1dG9tYXRpY2FsbHkgY2FsY3VsYXRlZAojIGZvciBldmVyeSBvYmplY3QgYnkgU2V1cmF0LiAgRm9yIG5vbi1VTUkgZGF0YSwgblVNSSByZXByZXNlbnRzIHRoZSBzdW0gb2YKIyB0aGUgbm9uLW5vcm1hbGl6ZWQgdmFsdWVzIHdpdGhpbiBhIGNlbGwgV2UgY2FsY3VsYXRlIHRoZSBwZXJjZW50YWdlIG9mCiMgbWl0b2Nob25kcmlhbCBnZW5lcyBoZXJlIGFuZCBzdG9yZSBpdCBpbiBwZXJjZW50Lm1pdG8gdXNpbmcgQWRkTWV0YURhdGEuCiMgV2UgdXNlIG9iamVjdEByYXcuZGF0YSBzaW5jZSB0aGlzIHJlcHJlc2VudHMgbm9uLXRyYW5zZm9ybWVkIGFuZAojIG5vbi1sb2ctbm9ybWFsaXplZCBjb3VudHMgVGhlICUgb2YgVU1JIG1hcHBpbmcgdG8gTVQtZ2VuZXMgaXMgYSBjb21tb24KIyBzY1JOQS1zZXEgUUMgbWV0cmljLgptaXRvLmZlYXR1cmVzIDwtIGdyZXAocGF0dGVybiA9ICJeTVQtIiwgeCA9IHJvd25hbWVzKHggPSBIQjEpLCB2YWx1ZSA9IFRSVUUpCnBlcmNlbnQubWl0byA8LSBNYXRyaXg6OmNvbFN1bXMoeCA9IEdldEFzc2F5RGF0YShvYmplY3QgPSBIQjEsIHNsb3QgPSAnY291bnRzJylbbWl0by5mZWF0dXJlcywgXSkgLyBNYXRyaXg6OmNvbFN1bXMoeCA9IEdldEFzc2F5RGF0YShvYmplY3QgPSBIQjEsIHNsb3QgPSAnY291bnRzJykpCiMgVGhlIFtbIG9wZXJhdG9yIGNhbiBhZGQgY29sdW1ucyB0byBvYmplY3QgbWV0YWRhdGEsIGFuZCBpcyBhIGdyZWF0IHBsYWNlIHRvIHN0YXNoIFFDIHN0YXRzCkhCMVtbJ3BlcmNlbnQubWl0byddXSA8LSBwZXJjZW50Lm1pdG8KYGBgCmBgYHtyfQpyYi5nZW5lcyA8LSByb3duYW1lcyhIQjEpW2dyZXAoIl5SUFtTTF0iLHJvd25hbWVzKEhCMSkpXQpwZXJjZW50LnJpYm8gPC0gTWF0cml4Ojpjb2xTdW1zKHggPSBHZXRBc3NheURhdGEob2JqZWN0ID0gSEIxLCBzbG90ID0gJ2NvdW50cycpW3JiLmdlbmVzLCBdKSAvIE1hdHJpeDo6Y29sU3Vtcyh4ID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IEhCMSwgc2xvdCA9ICdjb3VudHMnKSkKSEIxW1sncGVyY2VudC5yaWJvJ11dIDwtIHBlcmNlbnQucmlibwpgYGAKYGBge3J9ClZsblBsb3Qob2JqZWN0ID0gSEIxLCBmZWF0dXJlcyA9IGMoIm5GZWF0dXJlX1JOQSIsICJuQ291bnRfUk5BIiwgInBlcmNlbnQubWl0byIsICJwZXJjZW50LnJpYm8iKSwgbmNvbCA9IDQpCmBgYApgYGB7cn0KIyBUaGUgbnVtYmVyIG9mIGdlbmVzIGFuZCBVTUlzIChuR2VuZSBhbmQgblVNSSkgYXJlIGF1dG9tYXRpY2FsbHkgY2FsY3VsYXRlZAojIGZvciBldmVyeSBvYmplY3QgYnkgU2V1cmF0LiAgRm9yIG5vbi1VTUkgZGF0YSwgblVNSSByZXByZXNlbnRzIHRoZSBzdW0gb2YKIyB0aGUgbm9uLW5vcm1hbGl6ZWQgdmFsdWVzIHdpdGhpbiBhIGNlbGwgV2UgY2FsY3VsYXRlIHRoZSBwZXJjZW50YWdlIG9mCiMgbWl0b2Nob25kcmlhbCBnZW5lcyBoZXJlIGFuZCBzdG9yZSBpdCBpbiBwZXJjZW50Lm1pdG8gdXNpbmcgQWRkTWV0YURhdGEuCiMgV2UgdXNlIG9iamVjdEByYXcuZGF0YSBzaW5jZSB0aGlzIHJlcHJlc2VudHMgbm9uLXRyYW5zZm9ybWVkIGFuZAojIG5vbi1sb2ctbm9ybWFsaXplZCBjb3VudHMgVGhlICUgb2YgVU1JIG1hcHBpbmcgdG8gTVQtZ2VuZXMgaXMgYSBjb21tb24KIyBzY1JOQS1zZXEgUUMgbWV0cmljLgptaXRvLmZlYXR1cmVzIDwtIGdyZXAocGF0dGVybiA9ICJeTVQtIiwgeCA9IHJvd25hbWVzKHggPSBIQjQpLCB2YWx1ZSA9IFRSVUUpCnBlcmNlbnQubWl0byA8LSBNYXRyaXg6OmNvbFN1bXMoeCA9IEdldEFzc2F5RGF0YShvYmplY3QgPSBIQjQsIHNsb3QgPSAnY291bnRzJylbbWl0by5mZWF0dXJlcywgXSkgLyBNYXRyaXg6OmNvbFN1bXMoeCA9IEdldEFzc2F5RGF0YShvYmplY3QgPSBIQjQsIHNsb3QgPSAnY291bnRzJykpCiMgVGhlIFtbIG9wZXJhdG9yIGNhbiBhZGQgY29sdW1ucyB0byBvYmplY3QgbWV0YWRhdGEsIGFuZCBpcyBhIGdyZWF0IHBsYWNlIHRvIHN0YXNoIFFDIHN0YXRzCkhCNFtbJ3BlcmNlbnQubWl0byddXSA8LSBwZXJjZW50Lm1pdG8KYGBgCmBgYHtyfQpyYi5nZW5lcyA8LSByb3duYW1lcyhIQjQpW2dyZXAoIl5SUFtTTF0iLHJvd25hbWVzKEhCNCkpXQpwZXJjZW50LnJpYm8gPC0gTWF0cml4Ojpjb2xTdW1zKHggPSBHZXRBc3NheURhdGEob2JqZWN0ID0gSEI0LCBzbG90ID0gJ2NvdW50cycpW3JiLmdlbmVzLCBdKSAvIE1hdHJpeDo6Y29sU3Vtcyh4ID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IEhCNCwgc2xvdCA9ICdjb3VudHMnKSkKSEI0W1sncGVyY2VudC5yaWJvJ11dIDwtIHBlcmNlbnQucmlibwpWbG5QbG90KG9iamVjdCA9IEhCNCwgZmVhdHVyZXMgPSBjKCJuRmVhdHVyZV9STkEiLCAibkNvdW50X1JOQSIsICJwZXJjZW50Lm1pdG8iLCAicGVyY2VudC5yaWJvIiksIG5jb2wgPSA0KQpgYGAKYGBge3J9CiMgVGhlIG51bWJlciBvZiBnZW5lcyBhbmQgVU1JcyAobkdlbmUgYW5kIG5VTUkpIGFyZSBhdXRvbWF0aWNhbGx5IGNhbGN1bGF0ZWQKIyBmb3IgZXZlcnkgb2JqZWN0IGJ5IFNldXJhdC4gIEZvciBub24tVU1JIGRhdGEsIG5VTUkgcmVwcmVzZW50cyB0aGUgc3VtIG9mCiMgdGhlIG5vbi1ub3JtYWxpemVkIHZhbHVlcyB3aXRoaW4gYSBjZWxsIFdlIGNhbGN1bGF0ZSB0aGUgcGVyY2VudGFnZSBvZgojIG1pdG9jaG9uZHJpYWwgZ2VuZXMgaGVyZSBhbmQgc3RvcmUgaXQgaW4gcGVyY2VudC5taXRvIHVzaW5nIEFkZE1ldGFEYXRhLgojIFdlIHVzZSBvYmplY3RAcmF3LmRhdGEgc2luY2UgdGhpcyByZXByZXNlbnRzIG5vbi10cmFuc2Zvcm1lZCBhbmQKIyBub24tbG9nLW5vcm1hbGl6ZWQgY291bnRzIFRoZSAlIG9mIFVNSSBtYXBwaW5nIHRvIE1ULWdlbmVzIGlzIGEgY29tbW9uCiMgc2NSTkEtc2VxIFFDIG1ldHJpYy4KbWl0by5mZWF0dXJlcyA8LSBncmVwKHBhdHRlcm4gPSAiXk1ULSIsIHggPSByb3duYW1lcyh4ID0gSEI2KSwgdmFsdWUgPSBUUlVFKQpwZXJjZW50Lm1pdG8gPC0gTWF0cml4Ojpjb2xTdW1zKHggPSBHZXRBc3NheURhdGEob2JqZWN0ID0gSEI2LCBzbG90ID0gJ2NvdW50cycpW21pdG8uZmVhdHVyZXMsIF0pIC8gTWF0cml4Ojpjb2xTdW1zKHggPSBHZXRBc3NheURhdGEob2JqZWN0ID0gSEI2LCBzbG90ID0gJ2NvdW50cycpKQojIFRoZSBbWyBvcGVyYXRvciBjYW4gYWRkIGNvbHVtbnMgdG8gb2JqZWN0IG1ldGFkYXRhLCBhbmQgaXMgYSBncmVhdCBwbGFjZSB0byBzdGFzaCBRQyBzdGF0cwpIQjZbWydwZXJjZW50Lm1pdG8nXV0gPC0gcGVyY2VudC5taXRvCmBgYApgYGB7cn0KcmIuZ2VuZXMgPC0gcm93bmFtZXMoSEI2KVtncmVwKCJeUlBbU0xdIixyb3duYW1lcyhIQjYpKV0KcGVyY2VudC5yaWJvIDwtIE1hdHJpeDo6Y29sU3Vtcyh4ID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IEhCNiwgc2xvdCA9ICdjb3VudHMnKVtyYi5nZW5lcywgXSkgLyBNYXRyaXg6OmNvbFN1bXMoeCA9IEdldEFzc2F5RGF0YShvYmplY3QgPSBIQjYsIHNsb3QgPSAnY291bnRzJykpCkhCNltbJ3BlcmNlbnQucmlibyddXSA8LSBwZXJjZW50LnJpYm8KVmxuUGxvdChvYmplY3QgPSBIQjYsIGZlYXR1cmVzID0gYygibkZlYXR1cmVfUk5BIiwgIm5Db3VudF9STkEiLCAicGVyY2VudC5taXRvIiwgInBlcmNlbnQucmlibyIpLCBuY29sID0gNCkKYGBgCmBgYHtyfQojIFRoZSBudW1iZXIgb2YgZ2VuZXMgYW5kIFVNSXMgKG5HZW5lIGFuZCBuVU1JKSBhcmUgYXV0b21hdGljYWxseSBjYWxjdWxhdGVkCiMgZm9yIGV2ZXJ5IG9iamVjdCBieSBTZXVyYXQuICBGb3Igbm9uLVVNSSBkYXRhLCBuVU1JIHJlcHJlc2VudHMgdGhlIHN1bSBvZgojIHRoZSBub24tbm9ybWFsaXplZCB2YWx1ZXMgd2l0aGluIGEgY2VsbCBXZSBjYWxjdWxhdGUgdGhlIHBlcmNlbnRhZ2Ugb2YKIyBtaXRvY2hvbmRyaWFsIGdlbmVzIGhlcmUgYW5kIHN0b3JlIGl0IGluIHBlcmNlbnQubWl0byB1c2luZyBBZGRNZXRhRGF0YS4KIyBXZSB1c2Ugb2JqZWN0QHJhdy5kYXRhIHNpbmNlIHRoaXMgcmVwcmVzZW50cyBub24tdHJhbnNmb3JtZWQgYW5kCiMgbm9uLWxvZy1ub3JtYWxpemVkIGNvdW50cyBUaGUgJSBvZiBVTUkgbWFwcGluZyB0byBNVC1nZW5lcyBpcyBhIGNvbW1vbgojIHNjUk5BLXNlcSBRQyBtZXRyaWMuCm1pdG8uZmVhdHVyZXMgPC0gZ3JlcChwYXR0ZXJuID0gIl5NVC0iLCB4ID0gcm93bmFtZXMoeCA9IEhCNyksIHZhbHVlID0gVFJVRSkKcGVyY2VudC5taXRvIDwtIE1hdHJpeDo6Y29sU3Vtcyh4ID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IEhCNywgc2xvdCA9ICdjb3VudHMnKVttaXRvLmZlYXR1cmVzLCBdKSAvIE1hdHJpeDo6Y29sU3Vtcyh4ID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IEhCNywgc2xvdCA9ICdjb3VudHMnKSkKIyBUaGUgW1sgb3BlcmF0b3IgY2FuIGFkZCBjb2x1bW5zIHRvIG9iamVjdCBtZXRhZGF0YSwgYW5kIGlzIGEgZ3JlYXQgcGxhY2UgdG8gc3Rhc2ggUUMgc3RhdHMKSEI3W1sncGVyY2VudC5taXRvJ11dIDwtIHBlcmNlbnQubWl0bwpgYGAKYGBge3J9CnJiLmdlbmVzIDwtIHJvd25hbWVzKEhCNylbZ3JlcCgiXlJQW1NMXSIscm93bmFtZXMoSEI3KSldCnBlcmNlbnQucmlibyA8LSBNYXRyaXg6OmNvbFN1bXMoeCA9IEdldEFzc2F5RGF0YShvYmplY3QgPSBIQjcsIHNsb3QgPSAnY291bnRzJylbcmIuZ2VuZXMsIF0pIC8gTWF0cml4Ojpjb2xTdW1zKHggPSBHZXRBc3NheURhdGEob2JqZWN0ID0gSEI3LCBzbG90ID0gJ2NvdW50cycpKQpIQjdbWydwZXJjZW50LnJpYm8nXV0gPC0gcGVyY2VudC5yaWJvClZsblBsb3Qob2JqZWN0ID0gSEI3LCBmZWF0dXJlcyA9IGMoIm5GZWF0dXJlX1JOQSIsICJuQ291bnRfUk5BIiwgInBlcmNlbnQubWl0byIsICJwZXJjZW50LnJpYm8iKSwgbmNvbCA9IDQpCmBgYAoKYGBge3J9CiMgVGhlIG51bWJlciBvZiBnZW5lcyBhbmQgVU1JcyAobkdlbmUgYW5kIG5VTUkpIGFyZSBhdXRvbWF0aWNhbGx5IGNhbGN1bGF0ZWQKIyBmb3IgZXZlcnkgb2JqZWN0IGJ5IFNldXJhdC4gIEZvciBub24tVU1JIGRhdGEsIG5VTUkgcmVwcmVzZW50cyB0aGUgc3VtIG9mCiMgdGhlIG5vbi1ub3JtYWxpemVkIHZhbHVlcyB3aXRoaW4gYSBjZWxsIFdlIGNhbGN1bGF0ZSB0aGUgcGVyY2VudGFnZSBvZgojIG1pdG9jaG9uZHJpYWwgZ2VuZXMgaGVyZSBhbmQgc3RvcmUgaXQgaW4gcGVyY2VudC5taXRvIHVzaW5nIEFkZE1ldGFEYXRhLgojIFdlIHVzZSBvYmplY3RAcmF3LmRhdGEgc2luY2UgdGhpcyByZXByZXNlbnRzIG5vbi10cmFuc2Zvcm1lZCBhbmQKIyBub24tbG9nLW5vcm1hbGl6ZWQgY291bnRzIFRoZSAlIG9mIFVNSSBtYXBwaW5nIHRvIE1ULWdlbmVzIGlzIGEgY29tbW9uCiMgc2NSTkEtc2VxIFFDIG1ldHJpYy4KbWl0by5mZWF0dXJlcyA8LSBncmVwKHBhdHRlcm4gPSAiXk1ULSIsIHggPSByb3duYW1lcyh4ID0gSEIxMiksIHZhbHVlID0gVFJVRSkKcGVyY2VudC5taXRvIDwtIE1hdHJpeDo6Y29sU3Vtcyh4ID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IEhCMTIsIHNsb3QgPSAnY291bnRzJylbbWl0by5mZWF0dXJlcywgXSkgLyBNYXRyaXg6OmNvbFN1bXMoeCA9IEdldEFzc2F5RGF0YShvYmplY3QgPSBIQjEyLCBzbG90ID0gJ2NvdW50cycpKQojIFRoZSBbWyBvcGVyYXRvciBjYW4gYWRkIGNvbHVtbnMgdG8gb2JqZWN0IG1ldGFkYXRhLCBhbmQgaXMgYSBncmVhdCBwbGFjZSB0byBzdGFzaCBRQyBzdGF0cwpIQjEyW1sncGVyY2VudC5taXRvJ11dIDwtIHBlcmNlbnQubWl0bwpgYGAKYGBge3J9CnJiLmdlbmVzIDwtIHJvd25hbWVzKEhCMTIpW2dyZXAoIl5SUFtTTF0iLHJvd25hbWVzKEhCMTIpKV0KcGVyY2VudC5yaWJvIDwtIE1hdHJpeDo6Y29sU3Vtcyh4ID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IEhCMTIsIHNsb3QgPSAnY291bnRzJylbcmIuZ2VuZXMsIF0pIC8gTWF0cml4Ojpjb2xTdW1zKHggPSBHZXRBc3NheURhdGEob2JqZWN0ID0gSEIxMiwgc2xvdCA9ICdjb3VudHMnKSkKSEIxMltbJ3BlcmNlbnQucmlibyddXSA8LSBwZXJjZW50LnJpYm8KVmxuUGxvdChvYmplY3QgPSBIQjEyLCBmZWF0dXJlcyA9IGMoIm5GZWF0dXJlX1JOQSIsICJuQ291bnRfUk5BIiwgInBlcmNlbnQubWl0byIsICJwZXJjZW50LnJpYm8iKSwgbmNvbCA9IDQpCmBgYAoKYGBge3J9CiMgVGhlIG51bWJlciBvZiBnZW5lcyBhbmQgVU1JcyAobkdlbmUgYW5kIG5VTUkpIGFyZSBhdXRvbWF0aWNhbGx5IGNhbGN1bGF0ZWQKIyBmb3IgZXZlcnkgb2JqZWN0IGJ5IFNldXJhdC4gIEZvciBub24tVU1JIGRhdGEsIG5VTUkgcmVwcmVzZW50cyB0aGUgc3VtIG9mCiMgdGhlIG5vbi1ub3JtYWxpemVkIHZhbHVlcyB3aXRoaW4gYSBjZWxsIFdlIGNhbGN1bGF0ZSB0aGUgcGVyY2VudGFnZSBvZgojIG1pdG9jaG9uZHJpYWwgZ2VuZXMgaGVyZSBhbmQgc3RvcmUgaXQgaW4gcGVyY2VudC5taXRvIHVzaW5nIEFkZE1ldGFEYXRhLgojIFdlIHVzZSBvYmplY3RAcmF3LmRhdGEgc2luY2UgdGhpcyByZXByZXNlbnRzIG5vbi10cmFuc2Zvcm1lZCBhbmQKIyBub24tbG9nLW5vcm1hbGl6ZWQgY291bnRzIFRoZSAlIG9mIFVNSSBtYXBwaW5nIHRvIE1ULWdlbmVzIGlzIGEgY29tbW9uCiMgc2NSTkEtc2VxIFFDIG1ldHJpYy4KbWl0by5mZWF0dXJlcyA8LSBncmVwKHBhdHRlcm4gPSAiXk1ULSIsIHggPSByb3duYW1lcyh4ID0gSEIxMyksIHZhbHVlID0gVFJVRSkKcGVyY2VudC5taXRvIDwtIE1hdHJpeDo6Y29sU3Vtcyh4ID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IEhCMTMsIHNsb3QgPSAnY291bnRzJylbbWl0by5mZWF0dXJlcywgXSkgLyBNYXRyaXg6OmNvbFN1bXMoeCA9IEdldEFzc2F5RGF0YShvYmplY3QgPSBIQjEzLCBzbG90ID0gJ2NvdW50cycpKQojIFRoZSBbWyBvcGVyYXRvciBjYW4gYWRkIGNvbHVtbnMgdG8gb2JqZWN0IG1ldGFkYXRhLCBhbmQgaXMgYSBncmVhdCBwbGFjZSB0byBzdGFzaCBRQyBzdGF0cwpIQjEzW1sncGVyY2VudC5taXRvJ11dIDwtIHBlcmNlbnQubWl0bwpgYGAKYGBge3J9CnJiLmdlbmVzIDwtIHJvd25hbWVzKEhCMTMpW2dyZXAoIl5SUFtTTF0iLHJvd25hbWVzKEhCMTMpKV0KcGVyY2VudC5yaWJvIDwtIE1hdHJpeDo6Y29sU3Vtcyh4ID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IEhCMTMsIHNsb3QgPSAnY291bnRzJylbcmIuZ2VuZXMsIF0pIC8gTWF0cml4Ojpjb2xTdW1zKHggPSBHZXRBc3NheURhdGEob2JqZWN0ID0gSEIxMywgc2xvdCA9ICdjb3VudHMnKSkKSEIxM1tbJ3BlcmNlbnQucmlibyddXSA8LSBwZXJjZW50LnJpYm8KVmxuUGxvdChvYmplY3QgPSBIQjEzLCBmZWF0dXJlcyA9IGMoIm5GZWF0dXJlX1JOQSIsICJuQ291bnRfUk5BIiwgInBlcmNlbnQubWl0byIsICJwZXJjZW50LnJpYm8iKSwgbmNvbCA9IDQpCmBgYApgYGB7cn0KIyBUaGUgbnVtYmVyIG9mIGdlbmVzIGFuZCBVTUlzIChuR2VuZSBhbmQgblVNSSkgYXJlIGF1dG9tYXRpY2FsbHkgY2FsY3VsYXRlZAojIGZvciBldmVyeSBvYmplY3QgYnkgU2V1cmF0LiAgRm9yIG5vbi1VTUkgZGF0YSwgblVNSSByZXByZXNlbnRzIHRoZSBzdW0gb2YKIyB0aGUgbm9uLW5vcm1hbGl6ZWQgdmFsdWVzIHdpdGhpbiBhIGNlbGwgV2UgY2FsY3VsYXRlIHRoZSBwZXJjZW50YWdlIG9mCiMgbWl0b2Nob25kcmlhbCBnZW5lcyBoZXJlIGFuZCBzdG9yZSBpdCBpbiBwZXJjZW50Lm1pdG8gdXNpbmcgQWRkTWV0YURhdGEuCiMgV2UgdXNlIG9iamVjdEByYXcuZGF0YSBzaW5jZSB0aGlzIHJlcHJlc2VudHMgbm9uLXRyYW5zZm9ybWVkIGFuZAojIG5vbi1sb2ctbm9ybWFsaXplZCBjb3VudHMgVGhlICUgb2YgVU1JIG1hcHBpbmcgdG8gTVQtZ2VuZXMgaXMgYSBjb21tb24KIyBzY1JOQS1zZXEgUUMgbWV0cmljLgptaXRvLmZlYXR1cmVzIDwtIGdyZXAocGF0dGVybiA9ICJeTVQtIiwgeCA9IHJvd25hbWVzKHggPSBIQjE0KSwgdmFsdWUgPSBUUlVFKQpwZXJjZW50Lm1pdG8gPC0gTWF0cml4Ojpjb2xTdW1zKHggPSBHZXRBc3NheURhdGEob2JqZWN0ID0gSEIxNCwgc2xvdCA9ICdjb3VudHMnKVttaXRvLmZlYXR1cmVzLCBdKSAvIE1hdHJpeDo6Y29sU3Vtcyh4ID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IEhCMTQsIHNsb3QgPSAnY291bnRzJykpCiMgVGhlIFtbIG9wZXJhdG9yIGNhbiBhZGQgY29sdW1ucyB0byBvYmplY3QgbWV0YWRhdGEsIGFuZCBpcyBhIGdyZWF0IHBsYWNlIHRvIHN0YXNoIFFDIHN0YXRzCkhCMTRbWydwZXJjZW50Lm1pdG8nXV0gPC0gcGVyY2VudC5taXRvCmBgYApgYGB7cn0KcmIuZ2VuZXMgPC0gcm93bmFtZXMoSEIxNClbZ3JlcCgiXlJQW1NMXSIscm93bmFtZXMoSEIxNCkpXQpwZXJjZW50LnJpYm8gPC0gTWF0cml4Ojpjb2xTdW1zKHggPSBHZXRBc3NheURhdGEob2JqZWN0ID0gSEIxNCwgc2xvdCA9ICdjb3VudHMnKVtyYi5nZW5lcywgXSkgLyBNYXRyaXg6OmNvbFN1bXMoeCA9IEdldEFzc2F5RGF0YShvYmplY3QgPSBIQjE0LCBzbG90ID0gJ2NvdW50cycpKQpIQjE0W1sncGVyY2VudC5yaWJvJ11dIDwtIHBlcmNlbnQucmlibwpWbG5QbG90KG9iamVjdCA9IEhCMTQsIGZlYXR1cmVzID0gYygibkZlYXR1cmVfUk5BIiwgIm5Db3VudF9STkEiLCAicGVyY2VudC5taXRvIiwgInBlcmNlbnQucmlibyIpLCBuY29sID0gNCkKYGBgCmBgYHtyfQojIFRoZSBudW1iZXIgb2YgZ2VuZXMgYW5kIFVNSXMgKG5HZW5lIGFuZCBuVU1JKSBhcmUgYXV0b21hdGljYWxseSBjYWxjdWxhdGVkCiMgZm9yIGV2ZXJ5IG9iamVjdCBieSBTZXVyYXQuICBGb3Igbm9uLVVNSSBkYXRhLCBuVU1JIHJlcHJlc2VudHMgdGhlIHN1bSBvZgojIHRoZSBub24tbm9ybWFsaXplZCB2YWx1ZXMgd2l0aGluIGEgY2VsbCBXZSBjYWxjdWxhdGUgdGhlIHBlcmNlbnRhZ2Ugb2YKIyBtaXRvY2hvbmRyaWFsIGdlbmVzIGhlcmUgYW5kIHN0b3JlIGl0IGluIHBlcmNlbnQubWl0byB1c2luZyBBZGRNZXRhRGF0YS4KIyBXZSB1c2Ugb2JqZWN0QHJhdy5kYXRhIHNpbmNlIHRoaXMgcmVwcmVzZW50cyBub24tdHJhbnNmb3JtZWQgYW5kCiMgbm9uLWxvZy1ub3JtYWxpemVkIGNvdW50cyBUaGUgJSBvZiBVTUkgbWFwcGluZyB0byBNVC1nZW5lcyBpcyBhIGNvbW1vbgojIHNjUk5BLXNlcSBRQyBtZXRyaWMuCm1pdG8uZmVhdHVyZXMgPC0gZ3JlcChwYXR0ZXJuID0gIl5NVC0iLCB4ID0gcm93bmFtZXMoeCA9IEhCMTUpLCB2YWx1ZSA9IFRSVUUpCnBlcmNlbnQubWl0byA8LSBNYXRyaXg6OmNvbFN1bXMoeCA9IEdldEFzc2F5RGF0YShvYmplY3QgPSBIQjE1LCBzbG90ID0gJ2NvdW50cycpW21pdG8uZmVhdHVyZXMsIF0pIC8gTWF0cml4Ojpjb2xTdW1zKHggPSBHZXRBc3NheURhdGEob2JqZWN0ID0gSEIxNSwgc2xvdCA9ICdjb3VudHMnKSkKIyBUaGUgW1sgb3BlcmF0b3IgY2FuIGFkZCBjb2x1bW5zIHRvIG9iamVjdCBtZXRhZGF0YSwgYW5kIGlzIGEgZ3JlYXQgcGxhY2UgdG8gc3Rhc2ggUUMgc3RhdHMKSEIxNVtbJ3BlcmNlbnQubWl0byddXSA8LSBwZXJjZW50Lm1pdG8KYGBgCmBgYHtyfQpyYi5nZW5lcyA8LSByb3duYW1lcyhIQjE1KVtncmVwKCJeUlBbU0xdIixyb3duYW1lcyhIQjE1KSldCnBlcmNlbnQucmlibyA8LSBNYXRyaXg6OmNvbFN1bXMoeCA9IEdldEFzc2F5RGF0YShvYmplY3QgPSBIQjE1LCBzbG90ID0gJ2NvdW50cycpW3JiLmdlbmVzLCBdKSAvIE1hdHJpeDo6Y29sU3Vtcyh4ID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IEhCMTUsIHNsb3QgPSAnY291bnRzJykpCkhCMTVbWydwZXJjZW50LnJpYm8nXV0gPC0gcGVyY2VudC5yaWJvClZsblBsb3Qob2JqZWN0ID0gSEIxNSwgZmVhdHVyZXMgPSBjKCJuRmVhdHVyZV9STkEiLCAibkNvdW50X1JOQSIsICJwZXJjZW50Lm1pdG8iLCAicGVyY2VudC5yaWJvIiksIG5jb2wgPSA0KQpgYGAKYGBge3J9CiMgVGhlIG51bWJlciBvZiBnZW5lcyBhbmQgVU1JcyAobkdlbmUgYW5kIG5VTUkpIGFyZSBhdXRvbWF0aWNhbGx5IGNhbGN1bGF0ZWQKIyBmb3IgZXZlcnkgb2JqZWN0IGJ5IFNldXJhdC4gIEZvciBub24tVU1JIGRhdGEsIG5VTUkgcmVwcmVzZW50cyB0aGUgc3VtIG9mCiMgdGhlIG5vbi1ub3JtYWxpemVkIHZhbHVlcyB3aXRoaW4gYSBjZWxsIFdlIGNhbGN1bGF0ZSB0aGUgcGVyY2VudGFnZSBvZgojIG1pdG9jaG9uZHJpYWwgZ2VuZXMgaGVyZSBhbmQgc3RvcmUgaXQgaW4gcGVyY2VudC5taXRvIHVzaW5nIEFkZE1ldGFEYXRhLgojIFdlIHVzZSBvYmplY3RAcmF3LmRhdGEgc2luY2UgdGhpcyByZXByZXNlbnRzIG5vbi10cmFuc2Zvcm1lZCBhbmQKIyBub24tbG9nLW5vcm1hbGl6ZWQgY291bnRzIFRoZSAlIG9mIFVNSSBtYXBwaW5nIHRvIE1ULWdlbmVzIGlzIGEgY29tbW9uCiMgc2NSTkEtc2VxIFFDIG1ldHJpYy4KbWl0by5mZWF0dXJlcyA8LSBncmVwKHBhdHRlcm4gPSAiXk1ULSIsIHggPSByb3duYW1lcyh4ID0gSEIxNiksIHZhbHVlID0gVFJVRSkKcGVyY2VudC5taXRvIDwtIE1hdHJpeDo6Y29sU3Vtcyh4ID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IEhCMTYsIHNsb3QgPSAnY291bnRzJylbbWl0by5mZWF0dXJlcywgXSkgLyBNYXRyaXg6OmNvbFN1bXMoeCA9IEdldEFzc2F5RGF0YShvYmplY3QgPSBIQjE2LCBzbG90ID0gJ2NvdW50cycpKQojIFRoZSBbWyBvcGVyYXRvciBjYW4gYWRkIGNvbHVtbnMgdG8gb2JqZWN0IG1ldGFkYXRhLCBhbmQgaXMgYSBncmVhdCBwbGFjZSB0byBzdGFzaCBRQyBzdGF0cwpIQjE2W1sncGVyY2VudC5taXRvJ11dIDwtIHBlcmNlbnQubWl0bwpgYGAKYGBge3J9CnJiLmdlbmVzIDwtIHJvd25hbWVzKEhCMTYpW2dyZXAoIl5SUFtTTF0iLHJvd25hbWVzKEhCMTYpKV0KcGVyY2VudC5yaWJvIDwtIE1hdHJpeDo6Y29sU3Vtcyh4ID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IEhCMTYsIHNsb3QgPSAnY291bnRzJylbcmIuZ2VuZXMsIF0pIC8gTWF0cml4Ojpjb2xTdW1zKHggPSBHZXRBc3NheURhdGEob2JqZWN0ID0gSEIxNiwgc2xvdCA9ICdjb3VudHMnKSkKSEIxNltbJ3BlcmNlbnQucmlibyddXSA8LSBwZXJjZW50LnJpYm8KVmxuUGxvdChvYmplY3QgPSBIQjE2LCBmZWF0dXJlcyA9IGMoIm5GZWF0dXJlX1JOQSIsICJuQ291bnRfUk5BIiwgInBlcmNlbnQubWl0byIsICJwZXJjZW50LnJpYm8iKSwgbmNvbCA9IDQpCmBgYApgYGB7cn0KIyBUaGUgbnVtYmVyIG9mIGdlbmVzIGFuZCBVTUlzIChuR2VuZSBhbmQgblVNSSkgYXJlIGF1dG9tYXRpY2FsbHkgY2FsY3VsYXRlZAojIGZvciBldmVyeSBvYmplY3QgYnkgU2V1cmF0LiAgRm9yIG5vbi1VTUkgZGF0YSwgblVNSSByZXByZXNlbnRzIHRoZSBzdW0gb2YKIyB0aGUgbm9uLW5vcm1hbGl6ZWQgdmFsdWVzIHdpdGhpbiBhIGNlbGwgV2UgY2FsY3VsYXRlIHRoZSBwZXJjZW50YWdlIG9mCiMgbWl0b2Nob25kcmlhbCBnZW5lcyBoZXJlIGFuZCBzdG9yZSBpdCBpbiBwZXJjZW50Lm1pdG8gdXNpbmcgQWRkTWV0YURhdGEuCiMgV2UgdXNlIG9iamVjdEByYXcuZGF0YSBzaW5jZSB0aGlzIHJlcHJlc2VudHMgbm9uLXRyYW5zZm9ybWVkIGFuZAojIG5vbi1sb2ctbm9ybWFsaXplZCBjb3VudHMgVGhlICUgb2YgVU1JIG1hcHBpbmcgdG8gTVQtZ2VuZXMgaXMgYSBjb21tb24KIyBzY1JOQS1zZXEgUUMgbWV0cmljLgptaXRvLmZlYXR1cmVzIDwtIGdyZXAocGF0dGVybiA9ICJeTVQtIiwgeCA9IHJvd25hbWVzKHggPSBIQjE3KSwgdmFsdWUgPSBUUlVFKQpwZXJjZW50Lm1pdG8gPC0gTWF0cml4Ojpjb2xTdW1zKHggPSBHZXRBc3NheURhdGEob2JqZWN0ID0gSEIxNywgc2xvdCA9ICdjb3VudHMnKVttaXRvLmZlYXR1cmVzLCBdKSAvIE1hdHJpeDo6Y29sU3Vtcyh4ID0gR2V0QXNzYXlEYXRhKG9iamVjdCA9IEhCMTcsIHNsb3QgPSAnY291bnRzJykpCiMgVGhlIFtbIG9wZXJhdG9yIGNhbiBhZGQgY29sdW1ucyB0byBvYmplY3QgbWV0YWRhdGEsIGFuZCBpcyBhIGdyZWF0IHBsYWNlIHRvIHN0YXNoIFFDIHN0YXRzCkhCMTdbWydwZXJjZW50Lm1pdG8nXV0gPC0gcGVyY2VudC5taXRvCmBgYApgYGB7cn0KcmIuZ2VuZXMgPC0gcm93bmFtZXMoSEIxNylbZ3JlcCgiXlJQW1NMXSIscm93bmFtZXMoSEIxNykpXQpwZXJjZW50LnJpYm8gPC0gTWF0cml4Ojpjb2xTdW1zKHggPSBHZXRBc3NheURhdGEob2JqZWN0ID0gSEIxNywgc2xvdCA9ICdjb3VudHMnKVtyYi5nZW5lcywgXSkgLyBNYXRyaXg6OmNvbFN1bXMoeCA9IEdldEFzc2F5RGF0YShvYmplY3QgPSBIQjE3LCBzbG90ID0gJ2NvdW50cycpKQpIQjE3W1sncGVyY2VudC5yaWJvJ11dIDwtIHBlcmNlbnQucmlibwpWbG5QbG90KG9iamVjdCA9IEhCMTcsIGZlYXR1cmVzID0gYygibkZlYXR1cmVfUk5BIiwgIm5Db3VudF9STkEiLCAicGVyY2VudC5taXRvIiwgInBlcmNlbnQucmlibyIpLCBuY29sID0gNCkKYGBgCmBgYHtyfQojIFNldCB1cCBIQjEgb2JqZWN0CkhCMSA8LSBzdWJzZXQoeCA9IEhCMSwgc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gMjAwICYgbkZlYXR1cmVfUk5BIDwgMTAwMDAgJiBwZXJjZW50Lm1pdG8gPCAwLjE1KQoKIyBTZXQgdXAgSEI0IG9iamVjdApIQjQgPC0gc3Vic2V0KHggPSBIQjQsIHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDIwMCAmIG5GZWF0dXJlX1JOQSA8IDEwMDAwICYgcGVyY2VudC5taXRvIDwgMC4xNSkKCiMgU2V0IHVwIEhCNiBvYmplY3QKSEI2IDwtIHN1YnNldCh4ID0gSEI2LCBzdWJzZXQgPSBuRmVhdHVyZV9STkEgPiAyMDAgJiBuRmVhdHVyZV9STkEgPCAxMDAwMCAmIHBlcmNlbnQubWl0byA8IDAuMTUpCgojIFNldCB1cCBIQjcgb2JqZWN0CkhCNyA8LSBzdWJzZXQoeCA9IEhCNywgc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gMjAwICYgbkZlYXR1cmVfUk5BIDwgMTAwMDAgJiBwZXJjZW50Lm1pdG8gPCAwLjE1KQoKIyBTZXQgdXAgSEIxMiBvYmplY3QKSEIxMiA8LSBzdWJzZXQoeCA9IEhCMTIsIHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDIwMCAmIG5GZWF0dXJlX1JOQSA8IDEwMDAwICYgcGVyY2VudC5taXRvIDwgMC4xNSkKCiMgU2V0IHVwIEhCMTMgb2JqZWN0CkhCMTMgPC0gc3Vic2V0KHggPSBIQjEzLCBzdWJzZXQgPSBuRmVhdHVyZV9STkEgPiAyMDAgJiBuRmVhdHVyZV9STkEgPCAxMDAwMCAmIHBlcmNlbnQubWl0byA8IDAuMTUpCgojIFNldCB1cCBIQjE0IG9iamVjdApIQjE0IDwtIHN1YnNldCh4ID0gSEIxNCwgc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gMjAwICYgbkZlYXR1cmVfUk5BIDwgMTAwMDAgJiBwZXJjZW50Lm1pdG8gPCAwLjE1KQoKIyBTZXQgdXAgSEIxNSBvYmplY3QKSEIxNSA8LSBzdWJzZXQoeCA9IEhCMTUsIHN1YnNldCA9IG5GZWF0dXJlX1JOQSA+IDIwMCAmIG5GZWF0dXJlX1JOQSA8IDEwMDAwICYgcGVyY2VudC5taXRvIDwgMC4xNSkKCiMgU2V0IHVwIEhCMTYgb2JqZWN0CkhCMTYgPC0gc3Vic2V0KHggPSBIQjE2LCBzdWJzZXQgPSBuRmVhdHVyZV9STkEgPiAyMDAgJiBuRmVhdHVyZV9STkEgPCAxMDAwMCAmIHBlcmNlbnQubWl0byA8IDAuMTUpCgojIFNldCB1cCBIQjE3IG9iamVjdApIQjE3IDwtIHN1YnNldCh4ID0gSEIxNywgc3Vic2V0ID0gbkZlYXR1cmVfUk5BID4gMjAwICYgbkZlYXR1cmVfUk5BIDwgMTAwMDAgJiBwZXJjZW50Lm1pdG8gPCAwLjE1KQpgYGAKCgpgYGB7cn0KSEIxIDwtIE5vcm1hbGl6ZURhdGEoSEIxKQpIQjEgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoSEIxLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCgpIQjQgPC0gTm9ybWFsaXplRGF0YShIQjQpCkhCNCA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhIQjQsIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMjAwMCkKCkhCNiA8LSBOb3JtYWxpemVEYXRhKEhCNikKSEI2IDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKEhCNiwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAyMDAwKQoKSEI3IDwtIE5vcm1hbGl6ZURhdGEoSEI3KQpIQjcgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoSEI3LCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCgpIQjEyIDwtIE5vcm1hbGl6ZURhdGEoSEIxMikKSEIxMiA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhIQjEyLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCgpIQjEzIDwtIE5vcm1hbGl6ZURhdGEoSEIxMykKSEIxMyA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhIQjEzLCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCgpIQjE0IDwtIE5vcm1hbGl6ZURhdGEoSEIxNCkKSEIxNCA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhIQjE0LCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCgpIQjE1IDwtIE5vcm1hbGl6ZURhdGEoSEIxNSkKSEIxNSA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhIQjE1LCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCgpIQjE2IDwtIE5vcm1hbGl6ZURhdGEoSEIxNikKSEIxNiA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhIQjE2LCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCgpIQjE3IDwtIE5vcm1hbGl6ZURhdGEoSEIxNykKSEIxNyA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhIQjE3LCBzZWxlY3Rpb24ubWV0aG9kID0gInZzdCIsIG5mZWF0dXJlcyA9IDIwMDApCmBgYApgYGB7cn0KSEIxIDwtIEFkZE1ldGFEYXRhKEhCMSwgbWV0YWRhdGE9IkEiLCBjb2wubmFtZT0iSEIiKQpIQjQgPC0gQWRkTWV0YURhdGEoSEI0LCBtZXRhZGF0YT0iQiIsIGNvbC5uYW1lPSJIQiIpCkhCNiA8LSBBZGRNZXRhRGF0YShIQjYsIG1ldGFkYXRhPSJDIiwgY29sLm5hbWU9IkhCIikKSEI3IDwtIEFkZE1ldGFEYXRhKEhCNywgbWV0YWRhdGE9IkQiLCBjb2wubmFtZT0iSEIiKQpIQjEyIDwtIEFkZE1ldGFEYXRhKEhCMTIsIG1ldGFkYXRhPSJFIiwgY29sLm5hbWU9IkhCIikKSEIxMyA8LSBBZGRNZXRhRGF0YShIQjEzLCBtZXRhZGF0YT0iRiIsIGNvbC5uYW1lPSJIQiIpCkhCMTQgPC0gQWRkTWV0YURhdGEoSEIxNCwgbWV0YWRhdGE9IkciLCBjb2wubmFtZT0iSEIiKQpIQjE1IDwtIEFkZE1ldGFEYXRhKEhCMTUsIG1ldGFkYXRhPSJIIiwgY29sLm5hbWU9IkhCIikKSEIxNiA8LSBBZGRNZXRhRGF0YShIQjE2LCBtZXRhZGF0YT0iSSIsIGNvbC5uYW1lPSJIQiIpCkhCMTcgPC0gQWRkTWV0YURhdGEoSEIxNywgbWV0YWRhdGE9IkoiLCBjb2wubmFtZT0iSEIiKQpgYGAKYGBge3J9CkhCYmlnLmxpc3QgPC0gbGlzdChIQjEsIEhCNCwgSEI2LCBIQjcsIEhCMTIsIEhCMTMsIEhCMTQsIEhCMTUsIEhCMTYsIEhCMTcpIApgYGAKYGBge3J9CmZlYXR1cmVzIDwtIFNlbGVjdEludGVncmF0aW9uRmVhdHVyZXMob2JqZWN0Lmxpc3QgPSBIQmJpZy5saXN0KQpgYGAKYGBge3J9CkhCLmFuY2hvcnMgPC0gRmluZEludGVncmF0aW9uQW5jaG9ycyhvYmplY3QubGlzdCA9IEhCYmlnLmxpc3QsIGFuY2hvci5mZWF0dXJlcyA9IGZlYXR1cmVzKQpgYGAKYGBge3J9CiMgdGhpcyBjb21tYW5kIGNyZWF0ZXMgYW4gJ2ludGVncmF0ZWQnIGRhdGEgYXNzYXkKSEIuY29tYmluZWQgPC0gSW50ZWdyYXRlRGF0YShhbmNob3JzZXQgPSBIQi5hbmNob3JzKQpgYGAKCgpgYGB7cn0KIyBzcGVjaWZ5IHRoYXQgd2Ugd2lsbCBwZXJmb3JtIGRvd25zdHJlYW0gYW5hbHlzaXMgb24gdGhlIGNvcnJlY3RlZCBkYXRhIG5vdGUgdGhhdCB0aGUgb3JpZ2luYWwKIyB1bm1vZGlmaWVkIGRhdGEgc3RpbGwgcmVzaWRlcyBpbiB0aGUgJ1JOQScgYXNzYXkKRGVmYXVsdEFzc2F5KEhCLmNvbWJpbmVkKSA8LSAiaW50ZWdyYXRlZCIKCiMgUnVuIHRoZSBzdGFuZGFyZCB3b3JrZmxvdyBmb3IgdmlzdWFsaXphdGlvbiBhbmQgY2x1c3RlcmluZwpIQi5jb21iaW5lZCA8LSBTY2FsZURhdGEoSEIuY29tYmluZWQsIHZhcnMudG8ucmVncmVzcyA9IGMoIm5Db3VudF9STkEiLCAicGVyY2VudC5taXRvIiwgInBlcmNlbnQucmlibyIpLCB2ZXJib3NlID0gRkFMU0UpCmBgYApgYGB7cn0KSEIuY29tYmluZWQgPC0gUnVuUENBKEhCLmNvbWJpbmVkLCB2ZXJib3NlID0gRkFMU0UpCmBgYApgYGB7cn0KSEIuY29tYmluZWQgPC0gUnVuVU1BUChIQi5jb21iaW5lZCwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXMgPSAxOjMwLCBzZXQuc2VlZCgxMjMpKQpIQi5jb21iaW5lZCA8LSBGaW5kTmVpZ2hib3JzKEhCLmNvbWJpbmVkLCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IDE6MzApCkhCLmNvbWJpbmVkIDwtIEZpbmRDbHVzdGVycyhIQi5jb21iaW5lZCwgcmVzb2x1dGlvbiA9IDAuNCkKYGBgCgpgYGB7cn0KIyBWaXN1YWxpemF0aW9uCkRpbVBsb3QoSEIuY29tYmluZWQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBUUlVFLCByZXBlbCA9IFRSVUUpCmBgYAoKYGBge3J9CkRpbVBsb3QoSEIuY29tYmluZWQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgc3BsaXQuYnkgPSAiSEIiLCBuY29sID0gNCkKYGBgCmBgYHtyfQojIEhvdyBkbyBJIGNyZWF0ZSBhIFVNQVAgcGxvdCB3aGVyZSBjZWxscyBhcmUgY29sb3JlZCBieSByZXBsaWNhdGU/ICBGaXJzdCwgc3RvcmUgdGhlIGN1cnJlbnQKIyBpZGVudGl0aWVzIGluIGEgbmV3IGNvbHVtbiBvZiBtZXRhLmRhdGEgY2FsbGVkIENlbGxUeXBlCkhCLmNvbWJpbmVkJENlbGxUeXBlIDwtIElkZW50cyhIQi5jb21iaW5lZCkKIyBOZXh0LCBzd2l0Y2ggdGhlIGlkZW50aXR5IGNsYXNzIG9mIGFsbCBjZWxscyB0byByZWZsZWN0IHJlcGxpY2F0ZSBJRApJZGVudHMoSEIuY29tYmluZWQpIDwtICJzZXVyYXRfY2x1c3RlcnMiCkRpbVBsb3QoSEIuY29tYmluZWQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBUUlVFKQpgYGAKYGBgCmBgYHtyfQpwMiA8LSBEaW1QbG90KEhCLmNvbWJpbmVkLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSwgcmVwZWwgPSBUUlVFKQpwMgpgYGAKCmBgYHtyfQpzYXZlUkRTKEhCLmNvbWJpbmVkLCBmaWxlID0gIi9Vc2Vycy9wZW5nd3UvRG9jdW1lbnRzL0V4cGVyaW1lbnRzL3NjUk5Bc2VxL0hCY29tYmluZWQucmRzIikKYGBgCgpgYGB7cn0KRGltUGxvdChvYmplY3QgPSBIQi5jb21iaW5lZCwgcmVkdWN0aW9uID0gJ3VtYXAnLCBzcGxpdC5ieSA9ICJIQiIsIHdpZHRoID0gMjAwMCwgaGVpZ2h0ID0gMTUwMCwgdW5pdHMgPSAicHgiLCByZXMgPSAzMDApCnRpZmYoZmlsZSA9ICIvVm9sdW1lcy9iYWNrdXBzL1BlbmcvUmVzZWFyY2gvc2NSTkFzZXEvSEJjb21iaW5lZC50aWZmIiwgd2lkdGggPSAyMDAwLCBoZWlnaHQgPSAxNTAwLCB1bml0cyA9ICJweCIsIHJlcyA9IDMwMCkKZGV2Lm9mZigpCmBgYAoKYGBge3J9CiMgRm9yIHBlcmZvcm1pbmcgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYWZ0ZXIgaW50ZWdyYXRpb24sIHdlIHN3aXRjaCBiYWNrIHRvIHRoZSBvcmlnaW5hbCBkYXRhCkRlZmF1bHRBc3NheShIQi5jb21iaW5lZCkgPC0gIlJOQSIKQWxsQ2x1c3QubWFya2VycyA8LSBGaW5kQWxsTWFya2VycyhIQi5jb21iaW5lZCwgZ3JvdXBpbmcudmFyID0gIkhCIiwgdmVyYm9zZSA9IEZBTFNFKQp3cml0ZS5jc3YoQWxsQ2x1c3QubWFya2VycywiL1VzZXJzL3Blbmd3dS9Eb2N1bWVudHMvRXhwZXJpbWVudHMvc2NSTkFzZXEvYWxsY2x1c3RlcnMuY3N2Iixyb3cubmFtZXMgPSBUUlVFKQpgYGAKYGBge3J9CmNsdXN0ZXIwLm1hcmtlcnMgPC0gRmluZENvbnNlcnZlZE1hcmtlcnMoSEIuY29tYmluZWQsIGlkZW50LjEgPSAwLCBncm91cGluZy52YXIgPSAiSEIiLCB2ZXJib3NlID0gRkFMU0UpCndyaXRlLmNzdihjbHVzdGVyMC5tYXJrZXJzLCIvVXNlcnMvcGVuZ3d1L0RvY3VtZW50cy9FeHBlcmltZW50cy9zY1JOQXNlcS9jbHVzdGVyMC5jc3YiLHJvdy5uYW1lcyA9IFRSVUUpCmBgYApgYGB7cn0KY2x1c3RlcjEubWFya2VycyA8LSBGaW5kQ29uc2VydmVkTWFya2VycyhIQi5jb21iaW5lZCwgaWRlbnQuMSA9IDEsIGdyb3VwaW5nLnZhciA9ICJIQiIsIHZlcmJvc2UgPSBGQUxTRSkKd3JpdGUuY3N2KGNsdXN0ZXIxLm1hcmtlcnMsIi9Vc2Vycy9wZW5nd3UvRG9jdW1lbnRzL0V4cGVyaW1lbnRzL3NjUk5Bc2VxL2NsdXN0ZXIxLmNzdiIscm93Lm5hbWVzID0gVFJVRSkKYGBgCmBgYHtyfQpjbHVzdGVyMi5tYXJrZXJzIDwtIEZpbmRDb25zZXJ2ZWRNYXJrZXJzKEhCLmNvbWJpbmVkLCBpZGVudC4xID0gMiwgZ3JvdXBpbmcudmFyID0gIkhCIiwgdmVyYm9zZSA9IEZBTFNFKQp3cml0ZS5jc3YoY2x1c3RlcjIubWFya2VycywiL1VzZXJzL3Blbmd3dS9Eb2N1bWVudHMvRXhwZXJpbWVudHMvc2NSTkFzZXEvY2x1c3RlcjIuY3N2Iixyb3cubmFtZXMgPSBUUlVFKQpgYGAKYGBge3J9CmNsdXN0ZXIzLm1hcmtlcnMgPC0gRmluZENvbnNlcnZlZE1hcmtlcnMoSEIuY29tYmluZWQsIGlkZW50LjEgPSAzLCBncm91cGluZy52YXIgPSAiSEIiLCB2ZXJib3NlID0gRkFMU0UpCndyaXRlLmNzdihjbHVzdGVyMy5tYXJrZXJzLCIvVXNlcnMvcGVuZ3d1L0RvY3VtZW50cy9FeHBlcmltZW50cy9zY1JOQXNlcS9jbHVzdGVyMy5jc3YiLHJvdy5uYW1lcyA9IFRSVUUpCmBgYApgYGB7cn0KY2x1c3RlcjQubWFya2VycyA8LSBGaW5kQ29uc2VydmVkTWFya2VycyhIQi5jb21iaW5lZCwgaWRlbnQuMSA9IDQsIGdyb3VwaW5nLnZhciA9ICJIQiIsIHZlcmJvc2UgPSBGQUxTRSkKd3JpdGUuY3N2KGNsdXN0ZXI0Lm1hcmtlcnMsIi9Vc2Vycy9wZW5nd3UvRG9jdW1lbnRzL0V4cGVyaW1lbnRzL3NjUk5Bc2VxL2NsdXN0ZXI0LmNzdiIscm93Lm5hbWVzID0gVFJVRSkKYGBgCmBgYHtyfQpjbHVzdGVyNS5tYXJrZXJzIDwtIEZpbmRDb25zZXJ2ZWRNYXJrZXJzKEhCLmNvbWJpbmVkLCBpZGVudC4xID0gNSwgZ3JvdXBpbmcudmFyID0gIkhCIiwgdmVyYm9zZSA9IEZBTFNFKQp3cml0ZS5jc3YoY2x1c3RlcjUubWFya2VycywiL1VzZXJzL3Blbmd3dS9Eb2N1bWVudHMvRXhwZXJpbWVudHMvc2NSTkFzZXEvY2x1c3RlcjUuY3N2Iixyb3cubmFtZXMgPSBUUlVFKQpgYGAKYGBge3J9CmNsdXN0ZXI2Lm1hcmtlcnMgPC0gRmluZENvbnNlcnZlZE1hcmtlcnMoSEIuY29tYmluZWQsIGlkZW50LjEgPSA2LCBncm91cGluZy52YXIgPSAiSEIiLCB2ZXJib3NlID0gRkFMU0UpCndyaXRlLmNzdihjbHVzdGVyNi5tYXJrZXJzLCIvVXNlcnMvcGVuZ3d1L0RvY3VtZW50cy9FeHBlcmltZW50cy9zY1JOQXNlcS9jbHVzdGVyNi5jc3YiLHJvdy5uYW1lcyA9IFRSVUUpCmBgYApgYGB7cn0KY2x1c3RlcjcubWFya2VycyA8LSBGaW5kQ29uc2VydmVkTWFya2VycyhIQi5jb21iaW5lZCwgaWRlbnQuMSA9NywgZ3JvdXBpbmcudmFyID0gIkhCIiwgdmVyYm9zZSA9IEZBTFNFKQp3cml0ZS5jc3YoY2x1c3RlcjcubWFya2VycywiL1VzZXJzL3Blbmd3dS9Eb2N1bWVudHMvRXhwZXJpbWVudHMvc2NSTkFzZXEvY2x1c3RlcjcuY3N2Iixyb3cubmFtZXMgPSBUUlVFKQpgYGAKYGBge3J9CmNsdXN0ZXI4Lm1hcmtlcnMgPC0gRmluZENvbnNlcnZlZE1hcmtlcnMoSEIuY29tYmluZWQsIGlkZW50LjEgPTgsIGdyb3VwaW5nLnZhciA9ICJIQiIsIHZlcmJvc2UgPSBGQUxTRSkKd3JpdGUuY3N2KGNsdXN0ZXI4Lm1hcmtlcnMsIi9Vc2Vycy9wZW5nd3UvRG9jdW1lbnRzL0V4cGVyaW1lbnRzL3NjUk5Bc2VxL2NsdXN0ZXI4LmNzdiIscm93Lm5hbWVzID0gVFJVRSkKYGBgCmBgYHtyfQpjbHVzdGVyOS5tYXJrZXJzIDwtIEZpbmRDb25zZXJ2ZWRNYXJrZXJzKEhCLmNvbWJpbmVkLCBpZGVudC4xID05LCBncm91cGluZy52YXIgPSAiSEIiLCB2ZXJib3NlID0gRkFMU0UpCndyaXRlLmNzdihjbHVzdGVyOS5tYXJrZXJzLCIvVXNlcnMvcGVuZ3d1L0RvY3VtZW50cy9FeHBlcmltZW50cy9zY1JOQXNlcS9jbHVzdGVyOS5jc3YiLHJvdy5uYW1lcyA9IFRSVUUpCmBgYApgYGB7cn0KY2x1c3RlcjEwLm1hcmtlcnMgPC0gRmluZENvbnNlcnZlZE1hcmtlcnMoSEIuY29tYmluZWQsIGlkZW50LjEgPSAxMCwgZ3JvdXBpbmcudmFyID0gIkhCIiwgdmVyYm9zZSA9IEZBTFNFKQp3cml0ZS5jc3YoY2x1c3RlcjEwLm1hcmtlcnMsIi9Vc2Vycy9wZW5nd3UvRG9jdW1lbnRzL0V4cGVyaW1lbnRzL3NjUk5Bc2VxL2NsdXN0ZXIxMC5jc3YiLHJvdy5uYW1lcyA9IFRSVUUpCmBgYApgYGB7cn0KY2x1c3RlcjExLm1hcmtlcnMgPC0gRmluZENvbnNlcnZlZE1hcmtlcnMoSEIuY29tYmluZWQsIGlkZW50LjEgPSAxMSwgZ3JvdXBpbmcudmFyID0gIkhCIiwgdmVyYm9zZSA9IEZBTFNFKQp3cml0ZS5jc3YoY2x1c3RlcjExLm1hcmtlcnMsIi9Vc2Vycy9wZW5nd3UvRG9jdW1lbnRzL0V4cGVyaW1lbnRzL3NjUk5Bc2VxL2NsdXN0ZXIxMS5jc3YiLHJvdy5uYW1lcyA9IFRSVUUpCmBgYAoKYGBge3J9CiMgRXhhbXBsZSBmb3IgcGxvdHRpbmcgZ2VuZSBmZWF0dXJlcwpGZWF0dXJlUGxvdChvYmplY3QgPSBIQi5jb21iaW5lZCwgZmVhdHVyZXMgPSBjKCJGR0YxOSIsICJLTEIiLCAiRkdGUjQiKSkKdGlmZihmaWxlID0gIkZHRi50aWZmIiwgd2lkdGggPSAxNTAwLCBoZWlnaHQgPSAxNTAwLCB1bml0cyA9ICJweCIsIHJlcyA9IDMwMCkKZGV2Lm9mZigpCmBgYAoKYGBge3J9CiMgRXhhbXBsZSBmb3IgY2FsY3VsYXRpbmcgZ2VuZSBzaWduYXR1cmVzCkZldHZOb3JtIDwtIHJlYWQuY3N2KCcvVXNlcnMvcGVuZ3d1L0RvY3VtZW50cy9FeHBlcmltZW50cy9STkFzZXEvMTgwODA1RmluYWwvRmV0dk5vcm1fVG9wNTAuY3N2JywgaGVhZGVyPUYsIHNlcD0iLCIpCkZldHZOb3JtIDwtIGFzLm1hdHJpeChGZXR2Tm9ybSkKSEIuY29tYmluZWQgPC0gQWRkTW9kdWxlU2NvcmUoSEIuY29tYmluZWQsCiAgICAgICAgICAgICAgICAgIGZlYXR1cmVzID0gbGlzdChGZXR2Tm9ybSksCiAgICAgICAgICAgICAgICAgIG5hbWU9IkZldHZOb3JtIikKYGBgCmBgYHtyfQojIFBsb3Qgc2NvcmVzCkZlYXR1cmVQbG90KEhCLmNvbWJpbmVkLAogICAgICAgICAgICBmZWF0dXJlcyA9IGMoIkZldHZOb3JtMSIpLCBsYWJlbCA9IEZBTFNFLCByZXBlbCA9IFRSVUUpICsKICAgICAgICAgICAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvdXJzID0gcmV2KGJyZXdlci5wYWwobiA9IDExLCBuYW1lID0gIlJkQnUiKSkpCmBgYApgYGB7cn0KIyBFeGFtcGxlIGZvciB2aW9saW4gcGxvdHMKbXlfZ2VuZXMgPC0gSEIuY29tYmluZWRbcm93Lm5hbWVzKHN1YnNldChmRGF0YShIQi5jb21iaW5lZCksIGdlbmVfc2hvcnRfbmFtZSAlaW4lIGMoIkFGUCIsICJITkY0QSIsICJLUlQxOSIsICJTT1g0IikpKSxdCgp0aWZmKGZpbGUgPSAiQUZQR2VuZXNfVmlvbGluLnRpZmYiLCB3aWR0aCA9IDE1MDAsIGhlaWdodCA9IDE1MDAsIHVuaXRzID0gInB4IiwgcmVzID0gMzAwKQpwIDwtIHBsb3RfZ2VuZXNfdmlvbGluKG15X2dlbmVzLCBncm91cGluZyA9ICJjbHVzdGVyIiwgbmNvbD0yLCBtaW5fZXhwcj0wLjEsCiAgY29sb3JfYnkgPSAiY2x1c3RlciIpCnAgKyBnZW9tX2ppdHRlcihzaGFwZT0xNiwgcG9zaXRpb249cG9zaXRpb25faml0dGVyKDAuMikpCmRldi5vZmYoKQpgYGAKYGBge3J9CiMgRG90IHBsb3RzIC0gdGhlIHNpemUgb2YgdGhlIGRvdCBjb3JyZXNwb25kcyB0byB0aGUgcGVyY2VudGFnZSBvZiBjZWxscyBleHByZXNzaW5nIHRoZQojIGZlYXR1cmUgaW4gZWFjaCBjbHVzdGVyLiBUaGUgY29sb3IgcmVwcmVzZW50cyB0aGUgYXZlcmFnZSBleHByZXNzaW9uIGxldmVsCmZlYXR1cmVzLnBsb3QgPC0gYygiRkdGMSIsICJGR0YyIiwgIkZHRjMiLCAiRkdGNCIsICJGR0Y3IiwgIkZHRjgiLCAiRkdGOSIsICJGR0YxMCIsICJGR0YxMSIsICJGR0YxMiIsICJGR0YxMyIsICJGR0YxNCIsICJGR0YxNyIsICJGR0YxOCIsICJGR0YxOSIsICJGR0YyMCIsICJGR0YyMSIsICJGR0YyMiIsICJGR0YyMyIpCkRvdFBsb3QoSEIuY29tYmluZWQsIGZlYXR1cmVzID0gZmVhdHVyZXMucGxvdCwgZ3JvdXAuYnkgPSAiSEIiKSArIFJvdGF0ZWRBeGlzKCkKYGBgCgpgYGB7cn0KIyBEb3QgcGxvdHMgLSB0aGUgc2l6ZSBvZiB0aGUgZG90IGNvcnJlc3BvbmRzIHRvIHRoZSBwZXJjZW50YWdlIG9mIGNlbGxzIGV4cHJlc3NpbmcgdGhlCiMgZmVhdHVyZSBpbiBlYWNoIGNsdXN0ZXIuIFRoZSBjb2xvciByZXByZXNlbnRzIHRoZSBhdmVyYWdlIGV4cHJlc3Npb24gbGV2ZWwKZmVhdHVyZXMucGxvdCA8LSBjKCJGR0ZSMSIsICJGR0ZSMiIsICJGR0ZSMyIsICJGR0ZSNCIsICJLTEIiLCAiRUdGUiIsICJNRVQiLCAiSUdGMVIiLCAiSUdGMlIiLCAiSU5TUiIsICJFR0YiLCAiSEdGIiwgIklHRjEiLCAiSUdGMi4xIikKRG90UGxvdChIQi5jb21iaW5lZCwgZmVhdHVyZXMgPSBmZWF0dXJlcy5wbG90LCBncm91cC5ieSA9ICJIQiIpICsgUm90YXRlZEF4aXMoKQpgYGAKCgpgYGB7cn0KdW1hcENvb3JkIDwtIGFzLmRhdGEuZnJhbWUoRW1iZWRkaW5ncyhvYmplY3QgPSBIQi5jb21iaW5lZFtbInVtYXAiXV0pKQp1bWFwQ29vcmRtYXQgPC0gYXMubWF0cml4KHVtYXBDb29yZCkKYGBgCgpgYGB7cn0KIyBNb25vY2xlIGZvciBwc2V1ZG90aW1lIGFuYWx5c2VzCnJlbW90ZXM6Omluc3RhbGxfZ2l0aHViKCdzYXRpamFsYWIvc2V1cmF0LXdyYXBwZXJzJykKbGlicmFyeShtb25vY2xlMykKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoU2V1cmF0V3JhcHBlcnMpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KGRwbHlyKQoKc2V0LnNlZWQoMTIzNCkKYGBgCmBgYHtyfQpIQi5tb25vY2xlIDwtIGFzLmNlbGxfZGF0YV9zZXQoSEIuY29tYmluZWQpCkhCLm1vbm9jbGUgPC0gY2x1c3Rlcl9jZWxscyhIQi5tb25vY2xlLCBjbHVzdGVyX21ldGhvZCA9ICJsb3V2YWluIikKCnAxIDwtIHBsb3RfY2VsbHMoSEIubW9ub2NsZSwgY29sb3JfY2VsbHNfYnkgPSAiY2x1c3RlciIsIHNob3dfdHJhamVjdG9yeV9ncmFwaCA9IEZBTFNFKQpwMiA8LSBwbG90X2NlbGxzKEhCLm1vbm9jbGUsIGNvbG9yX2NlbGxzX2J5ID0gInBhcnRpdGlvbiIsIHNob3dfdHJhamVjdG9yeV9ncmFwaCA9IEZBTFNFKQp3cmFwX3Bsb3RzKHAxLCBwMikKYGBgCmBgYHtyfQppbnRlZ3JhdGVkLnN1YiA8LSBzdWJzZXQoYXMuU2V1cmF0KEhCLm1vbm9jbGUsIGFzc2F5ID0gTlVMTCksIG1vbm9jbGUzX3BhcnRpdGlvbnMgPT0gMSkKSEIubW9ub2NsZSA8LSBhcy5jZWxsX2RhdGFfc2V0KGludGVncmF0ZWQuc3ViKQpgYGAKYGBge3J9CkhCLm1vbm9jbGUgPC0gbGVhcm5fZ3JhcGgoSEIubW9ub2NsZSwgdXNlX3BhcnRpdGlvbiA9IFRSVUUsIHZlcmJvc2UgPSBGQUxTRSkKYGBgCmBgYHtyfQpwbG90X2NlbGxzKEhCLm1vbm9jbGUsCiAgICAgICAgICAgY29sb3JfY2VsbHNfYnkgPSAiY2x1c3RlciIsCiAgICAgICAgICAgbGFiZWxfZ3JvdXBzX2J5X2NsdXN0ZXI9RkFMU0UsCiAgICAgICAgICAgbGFiZWxfbGVhdmVzPUZBTFNFLAogICAgICAgICAgIGxhYmVsX2JyYW5jaF9wb2ludHM9RkFMU0UpCmBgYApgYGB7cn0KSEIubW9ub2NsZSA8LSBvcmRlcl9jZWxscyhIQi5tb25vY2xlLCByb290X2NlbGxzID0gY29sbmFtZXMoSEIubW9ub2NsZVssY2x1c3RlcnMoSEIubW9ub2NsZSkgPT0gNDddKSkKcGxvdF9jZWxscyhIQi5tb25vY2xlLAogICAgICAgICAgIGNvbG9yX2NlbGxzX2J5ID0gInBzZXVkb3RpbWUiLAogICAgICAgICAgIGdyb3VwX2NlbGxzX2J5ID0gImNsdXN0ZXIiLAogICAgICAgICAgIGxhYmVsX2NlbGxfZ3JvdXBzID0gRkFMU0UsCiAgICAgICAgICAgbGFiZWxfZ3JvdXBzX2J5X2NsdXN0ZXI9RkFMU0UsCiAgICAgICAgICAgbGFiZWxfbGVhdmVzPUZBTFNFLAogICAgICAgICAgIGxhYmVsX2JyYW5jaF9wb2ludHM9RkFMU0UsCiAgICAgICAgICAgbGFiZWxfcm9vdHMgPSBGQUxTRSwKICAgICAgICAgICB0cmFqZWN0b3J5X2dyYXBoX2NvbG9yID0gImdyZXk2MCIpCmBgYAoKQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkNtZCtPcHRpb24rSSouCgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkNtZCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLiAKClRoZSBwcmV2aWV3IHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlIGVkaXRvci4gQ29uc2VxdWVudGx5LCB1bmxpa2UgKktuaXQqLCAqUHJldmlldyogZG9lcyBub3QgcnVuIGFueSBSIGNvZGUgY2h1bmtzLiBJbnN0ZWFkLCB0aGUgb3V0cHV0IG9mIHRoZSBjaHVuayB3aGVuIGl0IHdhcyBsYXN0IHJ1biBpbiB0aGUgZWRpdG9yIGlzIGRpc3BsYXllZC4KCg==